组合
# 组合:是一个对象拥有一个属性,该属性的值是另外一个对象.
class Foo:
def __init__(self, m):
self.m = m
class Bar():
def __init__(self, n):
self.n = n
obj=Bar(10)
obj1 = Foo(20)
obj.x=obj1 # 超级对象,通过一个属性可以访问到另外一个对象的值
print(obj.x.m) # 20
# 继承一般情况用在:什么是什么的情况 is
# 组合一般用在:什么有什么的情况 has
反射
# 在Python中,反射指的是通过字符串来操作对象的属性
# 四个内置函数:
getattr: 获取属性 # 用的最多
setattr:设置属性
hasattr:判断是否有某个属性
delattr:删除
1、getattr: 获取属性(重要)
class Student():
school = 'SH'
def __init__(self,name, age):
self.name=name
self.age = age
def func(self):
print('from func')
stu = Student('kevin', 20)
print(stu."school") # 获取stu里的字符串形式
# 如果有,默认值无用,当你查的属性不存在的时候,就返回第三参数
res=getattr(stu, 'school1', 666) # SH 666
### 函数的用法
res=getattr(stu, 'func1', stu.index) #### 用的是最多的
res() # func1不存在时,返回stu.index,加括号()就会调用index()函数
"""必须掌握!!!!!!"""
2、 setattr:设置属性(了解)
setattr(stu, 'x', 666) # stu.x=666
print(stu.__dict__)
3、hasattr:判断是否有某个属性
print(hasattr(stu, 'func'))
if hasattr(stu, 'func'): # 如果stu有func函数
getattr(stu, 'func')() # 加括号,调用
else: # 如果没有就。。。
...
4、delattr:删除(了解)
delattr(stu, 'name')
# 等于del stu.name
print(stu.__dict__)
内置方法之魔术方式(重要)
特点: 双下划线开头的方法,它满足一定的条件就会自动触发,简称魔法
1、__init__
2、__str__,__repr__:
1. 打印对象的时候,输出对象的时候会自动触发类中得__str__方法
2. 返回值必须是字符串形式
3. 如果它跟__repr__方法同时存在,__str__的优先级更高
class Student():
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self): # 这个用的是最多的,优先级更高
print('str')
return 'from str'
def __repr__(self):
print('repr')
return 'from repr'
stu = Student('ly', 20)
print(stu) # 内存地址 # 全部
print('str:', str(stu)) # 返回值
3、__del__方法:
1.当你删除对象的时候会触发__del__的执行
2. 当整个脚本的程序都执行完毕的时候,也会触发__del__的执行
3. 一般用在用来在对象被删除时自动触发回收系统资源的操作
class MySQL:
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.f = open('a.txt', 'w')
def __del__(self): # 一般在垃圾回收机制中使用
print('from _del')
self.f.close()
mysql = MySQL('127.0.0.1', 3306)
print('1223')
print('1223') # 在所有程序执行完也会触发
print('1223')
del MySQL # 删除时会触发
4、isinstance 和 issubclass:
print(isinstance'hello', str)) # 判断'hello'是不是str类型
# True/False
print(issubclass(Bar1, Foo)) # 判断Bar是不是Foo的子类
5、__doc__:(了解)
class Foo:
"""
'我是描述信息asdasd'
'我是描述信息asdasd'
'我是描述信息asdasd'
"""
pass
class Bar(Foo):
pass
print(Foo.__doc__) # 可以拿到Foo里注释信息
print(Bar.__doc__) # 无法继承取得注释
6、__enter__和__exit__:
注意:1、只要出现with语句,先执行enter语句,返回值给f
2、执行代码块
3、代码块执行执行完,会触发__exit__语句
# with可以用在很多地方,但是with语句后的对象中的类必须要声明__enter__和__exit__
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
# return self
def __exit__(self):
print('with中代码块执行完毕时执行我啊')
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError() # 主动抛出异常
# 简答题:先聊聊with 的用法? 问with上下文管理协议的执行原理? 为什么打开文件只会可以自动关闭?
# 如果with代码块中出现了异常,则with语句之后的代码都不能正常执行
def __exit__(self, exc_type, exc_val, exc_tb): #异常类型、异常值、追溯信息
return True # 如果在exit里返回了True,with代码块中出现了异常,就相当于没有出现异常
7、__setattr__,__delattr__,__getattr__
class Foo:
x=1
def __init__(self,y):
self.y=y
def __getattr__(self, item):
print('找不到会触发')
def __setattr__(self, key, value):
print('找不到会触发')
# self.key=value # 用点语法,无限递归
self.__dict__[key]=value #需要手动设置
def __delattr__(self, item):
print('删除时会触发')
# del self.item # 无限递归了
self.__dict__.pop(item) # 不能用点语法,手动删除
obj=Foo(10)
obj.z # 会触发__getattr__和__setattr__
obj.a='a' # 会触发两次__setattr__
print(obj.a) # None
del obj.a # 会触发__dict__
8、__setitem__,__getitem__,__delitem__:
obj=Foo('tom')
obj.name # 没有触发__getitem__,点语法
obj['name'] # 当用中括号[]获取对象会触发
def __setitem__(self, key, value):
print('__setitem__')
self.__dict__[key] = value # 手动设置
obj.age=18 # 不会触发
obj['age'] = 18 # 触发
# 只是触发了__setitem__,但是并没有在def __setitem__中真正设置了数,这时,我们需 要手动在def中设置
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item) # 手动设置
obj=Foo('tom')
del obj['age'] # 手动设置
9、__call__:
obj=Foo()
print(obj)
obj() # 当对象加括号的时候会触发__call__的执行