Python之组合 反射

组合


# 组合:是一个对象拥有一个属性,该属性的值是另外一个对象.

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__的执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值