class Rectangle: def init(self): self.width = 0 self.height = 0 def setSize(self, size): self.width, self.height = size def getSzie(self): return self.width, self.height
但是每个操作都要有一个方法对应,有没有简单的方法来访问对象的属性呢?
只能用于新式类
property函数可以接受零个、一个、三个、或四个参数
其原型为property(fget, fset, fdel, doc)
__metaclass__=type
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def setSize(self, size):
self.width, self.height = size
def getSize(self):
return self.width, self.height
size = property(getSize, setSize) #注意这行代码,这样我们就可以简单地对size属性进行赋值和获取,相关的方法会自动调用
r = Rectangle()
r.size = 150, 100 #我们可以直接给属性赋值,setSize方法会被自动调用
r.size #我们可以直接获取属性的值,getSize方法会被自动调用
这两种方法并不是很重要,因为通常可以使用函数或者绑定方法来代替
__metaclass__ = type
#手动包装和替换方法的技术
class Myclass:
def smeth(): #没有self参数
print 'This is a static method'
smeth = staticmethod(smeth) #手动把smeth方法包装成staticmethod类型并且同名替换
def cmeth(cls): #用cls代替self参数
print 'This is a class method of', cls
cmeth = classmethod(cmeth) #与smeth类似
#新的装饰器(decorator)语法
class Myclass:
@staticmethod #在方法或函数的上方列出装饰器(@操作符)
def smeth():
print 'This is a static method'
@classmethod
def cmeth(cls):
print 'This is a class method of', cls
#装饰器可以有多个,但是应用的顺序与指定的顺序相反
Myclass.smeth() #可以直接对类调用静态方法
Myclass.cmeth() #也可以对类直接调用类方法
使用这些方法我们可以实现对象特性访问、赋值、删除的截断
#可以用这些方法来实现property函数中的Rectangle类
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def __setattr__(self, name, value): #如果赋值的特性不是name,这个方法也会被调用,两方面都要考虑,__getattr__同理
if name == 'size':
self.width, self.height = size
else:
self.__dict__[name] = value #可以直接通过修改__dict__返回的字典直接修改特性
#此处如果改成self.name = value的赋值操作,会导致__setattr__方法再次被调用并且陷入死循环,要注意!!!
def __getattr__(self, name): #这里不能使用__getattribute__,否则也会陷入死循环
if name == 'size':
return self.width, self.height #因为width和height特性是存在的,所以访问时不会再次调用这个方法
else:
raise AttributeError
#如何在__getattribute__方法内访问self的特性
__metaclass__ = type #__getattribute__方法只适用于新式类
class Object:
def __getattribute__(self, name):
return 'hahahhahahha'
class Person(Object): #Person是Object的子类
def __init__(self):
self.name = 'Zk'
self.age = 21
def __getattribute__(self, name):
return super(Object,self).__getattribute__(name)
#通过调用超类的__getattribute__方法
#而且这里的超类Object必须使用super函数
#super函数的参数是超类Object而不是Person(这和继承超类的初始值super(Person, self).__init__()不同)
#而且这个方法不受超类的__getattribute__方法返回值影响
a = Person()
a.name #得到不是“hahahahahhahah”哦!