之前我们可以给实例绑定属性,但是能不能给实例绑定方法呢??
class Hero(object):
pass
hero=Hero()
def setheroav_age(self, age): # 定义一个函数作为实例方法
self.age = age
from types import MethodType
hero.setheroav_age=MethodType(setheroav_age,hero) #把setheroav_age绑定给hero
hero.setheroav_age(100)#调用实例方法
print(hero.age)
print(hasattr(hero,'setheroav_age'))
#>> 100
#>> True
如果你想限制实例的属性怎么办呢??
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性,:
譬如只运行对name和age添加属性
class Hero(object):
__slots__ = ('name','age')#只允许绑定的属性名称
hero=Hero()
hero.name='tony'
hero.age=25
hero.rank=3
print(hero.name,hero.age,hero.rank)
#>> 显示rank不在attribute之内
对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的
背景:我们之前的类的属性是可以随便被更改的,为了解决这个问题,我们在类里面增加两个函数,
class Hero(object):
def getSelf_name(self):
return self._name
def setSelf_name(self,name):
heroname=['tony','thor','hulk']
if name not in heroname:
self._name=name
heroname.append(name)
else:
raise ValueError('name must not in heroname!')
hero=Hero()
hero.setSelf_name('spider_man')
print(hero.getSelf_name())
hero.setSelf_name('tony')
print(hero.getSelf_name())
但是这样感觉很复杂,能不能简洁一丢丢呢?Python内置的@property装饰器就是负责把一个方法变成属性调用的:
在程序上的体现就是:
class Hero(object):
@property #位置是在第一个
def Self_name(self): #注意:第一个函数名和下面那个相同的哦
return self._name
@Self_name.setter
def Self_name(self, name):
heroname = ['tony', 'thor', 'hulk']
if name not in heroname:
self._name = name
heroname.append(name)
else:
raise ValueError('name must not in heroname!')
hero = Hero()
# hero.setSelf_name('spider_man') 这是是之前的
hero.Self_name='spider_man' #用上装饰器之后,函数名就相当于一个‘属性’
print(hero.Self_name)
#>> spider_man
这个神奇的 @property,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。
通过装饰器,可以对‘函数变成的属性’进行可读写or只读只写得属性。譬如:
class Hero(object):
@property #位置是在第一个
def Self_name(self): #注意:第一个函数名和下面那个相同的哦
return self._name
@Self_name.setter
def Self_name(self, name):
heroname = ['tony', 'thor', 'hulk']
if name not in heroname:
self._name = name
heroname.append(name)
else:
raise ValueError('name must not in heroname!')
@property
def decoratename(self):
return 'I am avengers'+str(self._name)
hero = Hero()
# hero.setSelf_name('spider_man') 这是是之前的
hero.Self_name='spider_man' #用上装饰器之后,函数名就相当于一个‘属性’
print(hero.Self_name)
print(hero.decoratename)