对象属性管理
Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案。__dict__是用来存储对象属性的一个字典,其键为属性名,值为属性的值。
一、__dict__
Spring.dict['season']就是访问类属性,同时通过.号也可以访问该类属性
class Person(object):
name = 'python'
age = 18
def __init__(self):
self.sex = 'boy'
self.like = 'papapa'
@staticmethod
def stat_func():
print 'this is stat_func'
@classmethod
def class_func(cls):
print 'class_func'
person = Person()
print 'Person.__dict__: ', Person.__dict__
print 'person.__dict__: ', person.__dict__
运行结果:
Person.__dict__: {'__module__': '__main__', 'name': 'python', '__init__': <function __init__ at 0x000000000385B518>, 'class_func': <classmethod object at 0x0000000003847F78>, '__dict__': <attribute '__dict__' of 'Person' objects>, 'age': 18, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'stat_func': <staticmethod object at 0x00000000037CFAF8>}
person.__dict__: {'like': 'papapa', 'sex': 'boy'}
由此可见, 类的普通方法、类方法、静态方法、全局变量以及一些内置的属性都是放在类对象
dict里
而实例对象
中存储了一些self.xxx的一些东西
在类的继承中,子类有自己的dict, 父类也有自己的dict,子类的全局变量和方法放在子类的dict中,父类的放在父类dict中。
class Person(object):
name = 'python'
age = 18
def __init__(self):
self.sex = 'boy'
self.like = 'papapa'
@staticmethod
def stat_func():
print 'this is stat_func'
@classmethod
def class_func(cls):
print 'class_func'
class Hero(Person):
name = 'super man'
age = 1000
def __init__(self):
super(Hero, self).__init__()
self.is_good = 'yes'
self.power = 'fly'
person = Person()
print 'Person.__dict__: ', Person.__dict__
print 'person.__dict__: ', person.__dict__
hero = Hero()
print 'Hero.__dict__: ', Hero.__dict__
print 'hero.__dict__: ', hero.__dict__
运行结果:
Person.__dict__: {'__module__': '__main__', 'name': 'python', '__init__': <function __init__ at 0x000000000374B518>, 'class_func': <classmethod object at 0x0000000003750048>, '__dict__': <attribute '__dict__' of 'Person' objects>, 'age': 18, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'stat_func': <staticmethod object at 0x0000000003737FD8>}
person.__dict__: {'like': 'papapa', 'sex': 'boy'}
Hero.__dict__: {'age': 1000, '__doc__': None, '__module__': '__main__', '__init__': <function __init__ at 0x000000000374B668>, 'name': 'super man'}
hero.__dict__: {'is_good': 'yes', 'like': 'papapa', 'power': 'fly', 'sex': 'boy'}
从运行结果可以看出,类对象的dict虽然没有继承父类的,但是实例对象继承了父类的实例属性
二、_slots_
现在我们终于明白了,动态语言与静态语言的不同
动态语言:可以在运行的过程中,修改代码
静态语言:编译时已经确定好代码,运行过程中不能修改
如果我们想要限制实例的属性怎么办?比如,只允许对Person实例添加name和age属性。
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__
变量,来限制该class实例
能添加的属性:
class Person:
__slots__ = ("name", "age")
def __init__(self,name,age):
self.name = name
self.age = age
p = Person("老王",20)
p.score = 100
输出
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/test/app.py", line 8, in <module>
p.score = 100
AttributeError: 'Person' object has no attribute 'score'
注意:
使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
当你定义__slots__
后,Python就会为实例使用一种更加紧凑的内部表示。(__dict__
、__doc__
等属性都会不见,节省内存)
实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典。
所以__slots__
是创建大量对象时节省内存的方法。
__slots__
的副作用是作为一个封装工具来防止用户给实例增加新的属性。
尽管使用__slots__
可以达到这样的目的,但是这个并不是它的初衷。
三、属性管理
1. hasattr()函数
hasattr()函数用于判断对象是否包含对应的属性
语法:
hasattr(object,name)
参数:
object--对象
name--字符串,属性名
返回值:
如果对象有该属性返回True,否则返回False
示例:
class People:
country='China'
def __init__(self,name):
self.name=name
def people_info(self):
print('%s is xxx' %(self.name))
obj=People('aaa')
print(hasattr(People,'country'))
#返回值:True
print('country' in People.__dict__)
#返回值:True
print(hasattr(obj,'people_info'))
#返回值:True
print(People.__dict__)
##{'__module__': '__main__', 'country': 'China', '__init__': <function People.__init__ at 0x1006d5620>, 'people_info': <function People.people_info at 0x10205d1e0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
注意:调用hasattr()函数时,类中的方法也算对象的属性。
2. getattr()函数
描述:
getattr()函数用于返回一个对象属性值
语法:
getattr(object,name,default)
参数:
object--对象
name--字符串,对象属性
default--默认返回值,如果不提供该参数,在没有对于属性时,将触发AttributeError。
返回值:
返回对象属性值
class People:
country='China'
def __init__(self,name):
self.name=name
def people_info(self):
print('%s is xxx' %(self.name))
obj=getattr(People,'country')
print(obj)
#返回值China
#obj=getattr(People,'countryaaaaaa')
#print(obj)
#报错
# File "/getattr()函数.py", line 32, in <module>
# obj=getattr(People,'countryaaaaaa')
# AttributeError: type object 'People' has no attribute 'countryaaaaaa'
obj=getattr(People,'countryaaaaaa',None)
print(obj)
#返回值None
3. setattr()函数
描述:
setattr函数,用于设置属性值,该属性必须存在
语法:
setattr(object,name,value)
参数:
object--对象
name--字符串,对象属性
value--属性值
返回值:
无
class People:
country='China'
def __init__(self,name):
self.name=name
def people_info(self):
print('%s is xxx' %(self.name))
obj=People('aaa')
setattr(People,'x',111) #等同于People.x=111
print(People.x)
#obj.age=18
setattr(obj,'age',18)
print(obj.__dict__)
#{'name': 'aaa', 'age': 18}
print(People.__dict__)
#{'__module__': '__main__', 'country': 'China', '__init__': <function People.__init__ at 0x1007d5620>, 'people_info': <function People.people_info at 0x10215d1e0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None, 'x': 111}
4. delattr()函数
描述:
delattr函数用于删除属性
delattr(x,'foobar)相当于del x.foobar
语法:
delattr(object,name)
参数:
object--对象
name--必须是对象的属性
返回值:
无
class People:
country='China'
def __init__(self,name):
self.name=name
def people_info(self):
print('%s is xxx' %(self.name))
delattr(People,'country') #等同于del People.country
print(People.__dict__)
{'__module__': '__main__', '__init__': <function People.__init__ at 0x1006d5620>, 'people_info': <function People.people_info at 0x10073d1e0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
示例:
class Foo:
def run(self):
while True:
cmd=input('cmd>>: ').strip()
if hasattr(self,cmd):
func=getattr(self,cmd)
func()
def download(self):
print('download....')
def upload(self):
print('upload...')
# obj=Foo()
# obj.run()