OOP-内置成员及魔术方法

面向对象-OOP-内置成员和魔术方法

1. 内置成员

#定义一个类A
class A():
    name = 'cxy'
    age = 24
    def func(self):
        print('学到头秃')
a = A()
a.h = '99'  

# 获取类/对象的所属成员 类/对象.__dict__
res = A.__dict__  # 获取当前类的所属成员
res = a.__dict__   # 获取当前对象的所属成员

# 获取类的说明文档 类/对象.__doc__
【注意不管是通过类还是通过对象调用,获取的都是类的说明文档】
res = A.__doc__
res = a.__doc__

# 获取类名称组成的字符串
res = A.__name__

# 获取类所在的文件名称,如果是当前文件,显示为__main__
res = A.__module__

# __bases__ 获取当前类的父类列表
res = A.__base__ # 获取继承的第一个父类
res = A.__bases__ # 获取继承的所有的父类列表

# MRO列表  获取当前类的继承链列表
res = A.__mro__

2.方法的分类

  • 对象方法:A.func(self)

    特征:

    1. 在类中定义的方法,含有self参数

    2. 含有self的方法,只能使用对象进行调用,不能使用类去调用

      (除非传递一个对象进去,但是不推荐:A.func(‘a’)))

    3. 该方法会把调用的对象传递进来

    class A():
        
        #对象方法
        def func(self):
            print(self)
    
    a = A()
    a.func()
    >>><__main__.A object at 0x000001A6D3C05608>
    【此时传递的是object
  • 类方法:使用装饰器 @classmethod

    特征:

    1. 在类中定义的方法,使用装饰器 @classmethod 进行了装饰
    2. 方法中有cls这个行参。不需要实例化对象,直接使用类进行调用
    3. 会把调用这个方法的类传递进来
    4. 可以用对象调用,但是传递进去的依然是类
    class A():
        
        #类方法
        @classmethod
        def func(cls):
            print(cls)
            
    a = A()
    a.func()
    A.func()
    >>><class '__main__.A'>
      【此时传递的是class<class '__main__.A'>
      【就算使用对象a去调用,传递进来的还是类】
    
  • 绑定类方法

    特征:

    1. 在类中定义的方法
    2. 只能使用类进行调用
    3. 不会传递对象或者类进来
    class A():
    
        # 绑定类方法
        def func():
            print('绑定类方法')
    
    A.func()
    #如果使用对象调用func(),则会报错
    
  • 静态方法

    特征:

    1. 在类中定义的方法,使用了 装饰器 @staticmethod 进行了装饰
    2. 可以使用对象或者类进行调用
    3. 不会传递对象或者类进来
    class A():
    
        # 静态方法
        @staticmethod
        def func():
            print('staticmethod')
    
    a = A()        
    a.func()
    A.func()
    >>>staticmethod
       staticmethod
    

3.常用函数

class Demo():
    pass
class A():
    pass
class B(A):
    pass
class C(A):
    ccc = 'abc'
class D(B,C):
    name = 'a'
    __age = 20

    def say(self):
        pass

d = D()


'''检测类和对象相关'''
# 检测一个类是否为另一个类的子类
issubclass(子类,父类) 
res = issubclass(D,B)

# 检测一个对象是否是该类或该类的子类的实例化结果
isinstance(对象,) 
res = isinstance(d,B)
print(res)
>>>True
res = isinstance(d,A)
print(res)
>>>True
res = isinstance(d,Demo)
print(res)
>>>False

'''操作类和对象成员相关'''
# 检测类/对象是否包含指定名称的成员
hasattr(对象/,'成员名称')  
res = hasattr(d,'name')     

# 获取类/对象的成员(包括属性和方法)的值
getattr(对象/,'成员名称') 
res = getattr(d,'say')

# 设置类/对象的成员的值
setattr(对象/,'成员名称','成员的值') 
res = setattr(d,'name','ooo')
print(d.name)
>>>ooo

# 删除类/对象的成员,和 del 直接删除对象的成员是一样的结果
delattr(/对象,'成员名称') 
delattr(D,'name')

# 获取当前对象所以可以访问的成员的列表
# 不过一般用 对象.__dict__
dir(对象)
res = dir(d)
print(res)

4.类和对象相关的魔术方法

魔术方法就是不需要手动调用就可以自动执行的方法

1. __init__ 初始化方法  *****
    触发机制:当实例化对象之后就会立即触发的方法
    作用:   为当前创建的对象完成一些初始化的操作,比如:成员属性的赋值,方法的调用,打开或创建一些资源
    参数:   一个self,用于接收当前对象,其它参数根据需求进行定义即可
    返回值: 无
    注意事项:无

2. __new__ 构造方法    ****
    触发机制:实例化对象时自动触发(在__init__之前触发)
    作用:   控制对象创建的过程:选择是创建还是不创建
    		【可以在__new__里写一些判断,以此来控制是否创建对象】
    参数:   一个cls,用于接收当前类;其它参数根据初始化方法的参数进行决定
    返回值: 必须返回object.__new__(cls)进行对象的创建,如果没有返回值,则实例化对象的结果为None
    注意事项:
        (1)__new__方法的参数和__init__方法的参数要保持一致,除了第一个参数
        (2)必须返回object.__new__(cls)进行对象的创建,如果没有返回值,则实例化对象的结果为None
    应用场景:设计模式中的单例设计模式(在一些特殊场景才会用到)

3. __del__ 析构方法    *****
    触发机制:当该类对象被销毁时,自动触发
    作用: 关闭或释放对象创建时打开或创建的一些资源
    参数: 一个self,接收当前的对象
    返回值:无
    注意事项: 无

4. __call__          ***
    触发机制: 把对象当作函数直接调用时自动触发
    		  #比如说 a = A()  
        	  #然后   a()
    作用:    一般用于归纳类或对象的操作步骤,方便调用;
    		【就可以直接把对象当成函数来调用,有些时候会很方便】
    参数:   一个self接收当前对象,其它参数根据调用需求缺点
    返回值:  可有可无
 	
5.__len__
    触发机制: 当使用len函数去检测当前对象的时候自动触发
    		 #比如说  a = A()  
        	  #然后   len(a)
    作用:    代替对象使用len函数,并返回一个指定的属性的值的整型
    参数:    一个self,接收当前对象
    返回值:   必须有,并且必须是一个整型
    注意事项: 在__len__方法里的return代码为:
              return len(self.想要获取的属性名)

6.__str__
    触发机制: 当使用str或者print函数对对象进行操作时自动触发
    作用:   代替对象进行字符串的返回,可以自定义打印的信息
    		同时也可以通过str(对象)的方式来对返回的字符串进行字符串相关操作:
        	#比如说:res = str(obj).split()
		    #	    print(res)
             #此时就会把__str__方法返回的字符串进行切片
    参数:  一个self,接收当前对象
    返回值: 必须有,而且必须是字符串类型

7.__repr__
    触发机制:在使用repr方法对当前对象进行转换时自动触发
    作用:   可以设置repr函数操作对象的结果
    参数:   一个self,接收当前对象
    返回值: 必须有,而且必须是字符串类型的值
    注意:   正常情况下,如果没有__str__这个魔术方法,__repr__方法就会代替__str__魔术方法

8.__bool__
    触发机制: 当前使用bool函数转换当前对象时,自动触发;默认情况下,对象会转为True
    作用:    可以代替对象进行bool类型的转换,可以转换任何数据
    参数 :   一个self 接收对象
    返回值: 必须是一个布尔类型的返回值
'''str、repr以及其对应魔术方法的区别'''

#str和repr函数都可以把其它类型的值转为字符串
num = 521
r1 = str(num)
r2 = repr(num)
print(r1,type(r1))
print(r2,type(r2))
>>>521 <class 'str'>
   521 <class 'str'>
    
#repr解析的结果带了引号
num = '521'
r1 = str(num)
r2 = repr(num)
print(r1,type(r1))
print(r2,type(r2))
>>>521 <class 'str'>
   '521' <class 'str'>
    
'''
str和repr函数都能够把其它类型的数据转为字符串类型
str函数会把对象 转为 更适合人类阅读的形式
repr函数会把对象 转为 解释器读取的形式
如果数据对象并没有更明显的区别,str和repr的结果是一样的
'''

5.成员相关魔术方法

## 1. __getattribute__   优先级最高
def __getattribute__(self,item):
    触发机制:访问对象成员时自动触发,无论当前成员是否存在
    作用:   可以在获取对象成员时,对数据进行一些处理
    参数:   一个self接收对象,一个item接收当前访问的成员名称
    返回值: 可有可无,返回的值就是访问的结果
    注意事项:在当前的魔术方法中,禁止对当前对象的成员进行访问,会触发递归。【就是不能使用 对象.成员 的方式】
            如果想要在当前魔术方法中访问对象的成员必须使用 object 来进行访问
            格式: object.__getattribute__(self,item)

## 2. __getattr__
def __getattr__(self,item):
    触发机制: 当访问对象中不存在的成员时,自动触发
    作用:  防止访问不存在的成员时报错,也可以为不存在的成员进行赋值操作
    参数:  一个self接收当前对象,一个item接收当前访问的成员名称
    返回值: 可有可无
    注意事项: 当存在 __getattribute__ 方法时,会去执行 __getattribute__ 方法
    		也要注意,不要在当前的方法中再次去访问这个不存在的成员,会触发递归操作

## 3. __setattr__
def __setattr__(self,key,value):
    触发机制: 当给对象的成员进行赋值操作时会自动触发(包括添加,修改)【注意!如果该方法中没有给对象成员赋值,那么对象成员赋值失败】
    作用:   可以限制或管理对象成员的添加和修改操作
    参数: 1. self 接收当前对象  
           2. key 设置的成员名  
           3. val 设置的成员值
    返回值: 无
    注意事项:在当前的魔术方法中禁止给当前对象的成员直接进行赋值操作,会触发递归操作
            如果想要给当前对象的成员进行赋值,需要借助 object
            格式: object.__setattr__(self,key,value)
## 4. __delattr__
def __delattr__(self,item):
    触发机制: 当删除对象成员时自动触发。
    	【注意!如果该方法中没有删除对象成员,那么对象成员删除失败】
    作用: 可以去限制对象成员的删除,还可以防止删除不存在成员时报错
    参数: 1.self 接收当前对象  
    	  2.item 删除的成员名称
    返回值: 无
    注意事项: 在当前魔术方法中禁止直接删除对象的成员,会触发递归操作。
            如果想要删除当前对象的成员,那么需要借助 object
            格式: object.__delattr__(self,item)
#用__getattribute__方法,对接收的对象的属性进行一些操作
#比如说把name中间的字符隐藏(就是变为*)
class Person():
    name = 'cxy'

    def __getattribute__(self, item):
        # 在方法中使用 object来获取属性值
        res = object.__getattribute__(self,item)
        # 在方法中可以对访问的成员数据进行处理
        return res[0]+'*'+res[-1]

obj = Person()
print(obj.name)
>>>c*y

##6.访问成员的顺序

  1. 调用 __getattribute__魔术方法(最先执行)
  2. 调用数据描述符【后面会讲】
  3. 调用当前对象的成员
  4. 调用当前类的成员
  5. 调用非数据描述符【后面会讲】
  6. 调用父类的成员
  7. 调用__getattr__魔术方法(如果前面的全都不存在,才会调用“访问对象中不存在的成员时自动触发”的__getattr__魔术方法)

以上步骤时调用某个成员时的顺序,前面的能够调用成功,后面则不在执行;

也就是说,只有前面的不存在,才会去调用后面的。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值