python-面向对象编程二
2018-11-15 本文已影响7人
TAsama
为了给所有实例都绑定方法,可以给class绑定方法:
def set_score(self, score):
self.score = score
class Student(object):
pass
Student.set_score = set_score
st1 = Student()
st1.set_score(100)
print(st1.score)
通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。
限制,添加新的属性,使用__ slots __
class Person(object):
__slots__ = ('name', 'age')
这样当给对象添加新的属性时就会报错。
使用slots要注意,slots定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
使用@property
使用"@property"将类内函数定义为getter方法
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
@property
def name(self):
return self.__name
@property
def score(self):
return self.__score
@name.setter # 添加setter方法
def name(self, value):
if not isinstance(value, str):
raise ValueError('name must be a string')
self.__name = value
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer')
if value < 0 or value > 100:
raise ValueError('socre must between 0 ~ 100')
self.__score = value
st1 = Student('h1', 10)
print(st1.score)
st1.score = 20
练习
请利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution
class Screen(object):
def __init__(self):
pass
@property
def width(self):
return self._width
@width.setter
def width(self, value):
self._width = value
@property
def height(self):
return self._height
@height.setter
def height(self, value):
self._height = value
@property # 只读属性就不需要设置setter方法了
def resolution(self):
return self._width * self._height
特殊方法
1. __ str __
类似 OC的description方法, 返回字符串
class Student(object):
def __init__(self):
pass
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
def __str__(self):
return 'Student name = %s' % self.name
2. __ repr__
调试服务直接打印调用的时这个方法,一般与__ str __保持一致
__repr__ = __str__
3. __ iter __
使对象可以用for循环迭代,返回一个迭代对象
4. __ next __
使对象成为一个迭代对象
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
if self.a > 10:
raise StopIteration()
return self.a
5. __ getitem __
像list那样按照下标取出元素
class FibSub(Fib):
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
如果想要具有切片的能力还需要改造一下:
class FibSlice(FibSub):
def __getitem__(self, n):
if isinstance(n, int):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice): # 判断为切片类型
start = n.start # 获取到range的起始
stop = n.stop # 获取到range的结尾
if start is None:
start = 0
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L
6. __ getattr __
当找不到某属性的时候,会在内部调用这个函数。
例:链式调用, 拼URL链接
class Chain(object):
def __init__(self, path = ''):
self._path = path
def __getattr__(self, attr):
return Chain('%s/%s' % (self._path, attr))
def __str__(self):
return self._path
def user(self, name):
return Chain('%s/%s' % (self._path, name))
s = Chain().user('hello').names.list
print(s)
>>> /hello/names/list
7. __ call __
只需要定义一个call()方法,就可以直接对实例进行调用
class myStudent(Student):
def __init__(self):
pass
def __call__(self, num):
print(num)
s = myStudent()
s(5)
callable()函数
通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
def p(*args, **kw):
print(*args, **kw)
p(callable(p()))
p(callable(max))
p(callable([1, 2, 3]))
p(callable(None))
p(callable('str'))