一、组合补充(重要程度*****)
分析如下几个示例的代码和结果,并作出总结:
# #####示例一:验证 类 或 对象 是否能做字典的key
class Foo:
pass
user_info = {
Foo : 1, # 类 做字典的key
Foo() : 5 # 对象 做字典的key
}
print(user_info)
# {<class '__main__.Foo'>: 1, <__main__.Foo object at 0x00000000029284E0>: 5}
# #####示例二:对象中到底有什么?
class Foo(object):
def __init__(self,age):
self.age = age
def display(self):
print(self.age)
data_list = [Foo(8),Foo(9)]
for item in data_list:
print(item.age,item.display())
# 结果为:
# 8
# 8 None
# 9
# 9 None
# #####示例三.
class StarkConfig(object):
def __init__(self,num):
self.num = num
def changelist(self,request):
print(self.num,request)
class RoleConfig(StarkConfig):
def changelist(self,request):
print('666')
# 创建了一个列表,列表中有三个对象(实例)
config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)]
for item in config_obj_list:
print(item.num)
# 结果为:
# 1
# 2
# 3
# 分析:RoleConfig类中没有__init__方法,创建对象时又传了一个参数3,
# 所以就去父级查找有没有__init__,有则执行,在所创建的对象中封装数据3
# #####示例四
class StarkConfig(object):
def __init__(self,num):
self.num = num
def changelist(self,request):
print(self.num,request)
def run(self):
self.changelist(999)
class RoleConfig(StarkConfig):
def changelist(self,request):
print(666,self.num)
config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)]
config_obj_list[1].run() # 2 999
config_obj_list[2].run() # 666 3
# #####示例五
class UserInfo(object):
pass
class Department(object):
pass
class StarkConfig(object):
def __init__(self,num):
self.num = num
def changelist(self,request):
print(self.num,request)
def run(self):
self.changelist(999)
class RoleConfig(StarkConfig):
def changelist(self,request):
print(666,self.num)
class AdminSite(object):
def __init__(self):
self._registry = {}
def register(self,k,v):
self._registry[k] = v(k)
site = AdminSite()
site.register(UserInfo,StarkConfig)
site.register(Department,StarkConfig)
print(len(site._registry)) # 2
for k,row in site._registry.items():
row.run()
# 结果为:
# <class '__main__.UserInfo'> 999
# <class '__main__.Department'> 999
总结:
1)对象 和 类 可以做字典的key;
2)明确对象中到底封装了什么;
3)哪个对象.方法,那么self就是这个对象,就从这个对象的类开始找;
二、主动调用其他类的成员(***)
如何主动调用其他类的成员,如下两种方式:
# #####方式一:Base.实例方法(自己传self) 与继承无关
class Base(object):
def f1(self):
print('5个功能', self)
class Foo(object):
def f1(self):
print('3个功能')
Base.f1(self) # 此时,参数必须要写,python不会自动传,写什么传什么
obj = Foo()
obj.f1()
# 结果为:
# 3个功能
# 5个功能 <__main__.Foo object at 0x0000000002718D68>
# #####方式二:按照类的继承顺序,找下一个.
class Foo(object):
def f1(self):
super().f1()
print('3个功能')
class Bar(object):
def f1(self):
print('6个功能')
class Info(Foo,Bar): # 查找顺序:Info Foo Bar
pass
obj = Info()
obj.f1()
# 结果为:
# 6个功能
# 3个功能
三、特殊成员(目前是***,越往后期越重要,越看源码用的越多)
1、按照某种语法会自动执行某些方法,如下示例:
class Foo(object):
def __init__(self, a1, a2):
self.a1 = a1
self.a2 = a2
def __call__(self, *args, **kwargs):
print('call', args, kwargs)
return 123
def __getitem__(self, item):
print(item)
return 8
def __setitem__(self, key, value):
print(key, value, 'setitem')
def __delitem__(self, key):
print(key)
def __add__(self, other):
return self.a1 + other.a2
def __enter__(self):
print('enter')
return '执行__enter__方法'
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
# 1. 类名() 自动执行 __init__
obj = Foo(1,2)
# 2. 对象() 自动执行 __call__
ret = obj(6,4,2,k1=456) # call (6, 4, 2) {'k1': 456}
print(ret) # 123
# 3. 对象['xx'] 自动执行 __getitem__
ret = obj['yu']
print(ret) # yu
# 4. 对象['xx'] = 11 自动执行 __setitem__
obj['k1'] = 123 # k1 123 setitem
# 5. del 对象[xx] 自动执行 __delitem__
del obj['delitem'] # delitem
# 6. 对象+对象 自动执行 __add__
obj1 = Foo(1,2)
obj2 = Foo(88,99)
ret = obj2 + obj1
print(ret) # 90
# 7. with 对象 自动执行 __enter__ / __exit__
obj = Foo(1,2)
with obj as f:
print(f) # 执行__enter__方法
print('内部代码')
2、真正的构造方法
class Foo(object):
def __init__(self, a1, a2): # 初始化方法
"""
为空对象进行数据初始化
"""
self.a1 = a1
self.a2 = a2
def __new__(cls, *args, **kwargs): # 构造方法
"""
创建一个空对象,
若不写__new__,则会由所有类的父类object的__new__来创建
:return:
"""
return object.__new__(cls) # Python内部创建一个当前类的对象并返回(初创时内部是空的.)
obj1 = Foo(1,2)
print(obj1)