¥面向对象之内置方法¥

面向对象内置方法

【一】方法

  • Python的Class机制内置了很多特殊的方法来帮助使用者高度定制自己的类

  • 这些内置方法都是以双下划线开头和结尾的,会在满足某种条件时自动触发

__init__    :初始化对象时触发
__del__     :销毁类时触发
__new__     :构造类时触发
__str__     :str函数或者print函数触发
__repr__    :repr或者交互式解释器触发
__doc__     :打印类内的注释内容
__enter__   :打开文档触发(with语句打开的时候触发)
__exit__    :关闭文档触发(with语句关闭的时候触发)
__getattr__ : 访问不存在的属性时调用
__setattr__ :设置实例对象的一个新的属性时调用
__delattr__ :删除一个实例对象的属性时调用
__setitem__ :列表添加值
__getitem__ :将对象当作list使用 
__delitem__ :列表删除值
__call__    :对象后面加括号,触发执行
__iter__    :迭代器
  • 方法__init__(),__del__(),__init__()

    • 这个方法是一个类的构造函数,与之对应的__del__()是析构函数,通过此方法我们可以定义一个对象的初始操作。

    • 但实际上,新式类的__new__()才是真正的初始化函数。

class A(object):
    def __init__(self):
        print('__init__')
​
    def __new__(cls, *args, **kwargs):
        print('__new__')
        # cls表示一个类,一个当前要被实例化的类,参数由py解释器自动提供
        return super().__new__(cls, *args, **kwargs)
​
    def __del__(self):
        print('__del__')
​
​
a = A()
print('do something')
print("111")
# __new__
# __init__
# do something
# 111
# __del__
  • 方法__str__:str函数或者print函数触发

    • __str__方法会在对象被打印时自动触发

    • print功能打印的就是它的返回值

    • 我们通常基于方法来定制对象的打印信息

    • 该方法必须返回字符串类型

  • 方法的返回值必须是字符串,否则抛出异常

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age
​
    def __str__(self):
        # 返回类型必须是字符串
        return f'<Name:{self.name} Age:{self.age}>'
​
​
person = People('dream', 18)
print(person)  # 触发p.__str__(),拿到返回值后进行打印
# <Name:dream Age:18>
  • 方法__repr__

    • repr或者交互式解释器触发

  • 方法的返回值必须是字符串,否则抛出异常

class School:
    def __init__(self, name, addr, type):
        self.name = name
        self.addr = addr
        self.type = type
​
    def __repr__(self):
        return 'School(%s,%s)' % (self.name, self.addr)
​
    def __str__(self):
        return '(%s,%s)' % (self.name, self.addr)
​
s1 = School('dreamCity', '北京', '私立')
print('from repr: ', repr(s1))#from repr:  School(dreamCity,北京)
print('from str: ', str(s1))#from str:  (dreamCity,北京)
print(s1)#(dreamCity,北京)
  • __del__方法

    • __del__会在对象被删除时自动触发。

class Person():
    def __init__(self, name, age):
        print(f'这是 :>>>> {name} , age :>>>> {age}')
​
    def __del__(self):
        print(f"我离开你了")
​
​
person = Person("dream", 18)
print("这是断层")
# 这是 :>>>> dream , age :>>>> 18
# 这是断层
# 我离开你了
  • 方法isinstance(obj,cls)

    • isinstance(obj,cls)检查是否obj是否是类cls 的对象

class Bar():
    pass
​
class Foo(object):
    pass
​
foo = Foo()
bar = Bar()
# isinstance(obj,cls)检查是否obj是否是类cls的对象
res_Foo = isinstance(foo, Foo)
res_Bar = isinstance(foo, Bar)
print(res_Foo)#True
print(res_Bar)#False
  • 方法issubclass(sub,super)

    • issubclass(sub, super)检查sub类是否是 super 类的派生类

class Foo(object):
    pass
​
class Bar(Foo):
    pass
​
res = issubclass(Bar, Foo)
print(res)#True
  • 方法__doc__

    • 打印类内的注释内容

class Foo:
    '我是描述信息'
    pass
​
print(Foo.__doc__)
#我是描述信息
  • 方法__enter____exit__

    • 打开文档触发

  • 为了让一个对象兼容with语句,必须在这个对象的类中声明__enter____exit__方法

class Open:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
        # return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')


with Open('a.txt') as f:
    print('=====>执行代码块')
#出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
# =====>执行代码块
# with中代码块执行完毕时执行我啊
  • __exit__()中的三个参数分别代表

    • 异常类型

    • 异常值

    • 追溯信息

  • with语句中代码块出现异常,则with后的代码都无法执行

  • 方法__setattr____delattr__,__getattr__

    • __getattr__(self, name): 访问不存在的属性时调用

    • __setattr__(self, name, value):设置实例对象的一个新的属性时调用

    • __delattr__(self, name):删除一个实例对象的属性时调用

class Foo:
    x = 1

    def __init__(self, y):
        self.y = y

    def __getattr__(self, item):
        print(f'----> from getattr:你找的属性不存在 :>>>> {item}')

    def __setattr__(self, key, value):
        print(f'----> from setattr  key : {key}  value : {value}')
        # self.key=value #这就无限递归了,你好好想想
        # self.__dict__[key]=value #应该使用它

    def __delattr__(self, item):
        print(f'----> from delattr :>>>> {item}')
        # del self.item #无限递归了
        self.__dict__.pop(item)


# __setattr__添加/修改属性会触发它的执行
f1 = Foo(10)#----> from setattr  key : y  value : 10

# 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
print(f1.__dict__)#{}
f1.z = 3#----> from setattr  key : z  value : 3
print(f1.__dict__)#{}

#  # __delattr__删除属性的时候会触发
f1.__dict__['a'] = 3  # 我们可以直接修改属性字典,来完成添加/修改属性的操作
print(f1.__dict__)#{'a': 3}
del f1.a#----> from delattr :>>>> a
print(f1.__dict__)#{}

# __getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx#----> from getattr:你找的属性不存在 :>>>> xxxxxx
  • 对象属性查找顺序

    • 首先访问__getattribute__()魔法方法(隐含默认调用,无论何种情况,均会调用此方法

    • 去实例对象t中查找是否具备该属性: t.__dict__中查找,每个类和实例对象都有一个__dict__的属性

    • 若在t.__dict__中找不到对应的属性, 则去该实例的类中寻找,即 t.__class__.__dict__

    • 若在实例的类中也招不到该属性,则去父类中寻找,即t.__class__.__bases__.__dict__中寻找

    • 若以上均无法找到,则会调用__getattr__方法,执行内部的命令(若未重载 __getattr__方法,则直接报错:AttributeError)

  • 方法__setitem__,__getitem__,__delitem__

  • __setitem__ :列表添加值

  • __getitem__:将对象当作list使用

  • __delitem__:列表删除值

class Foo:
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)

    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)


f1 = Foo('sb')

#执行def __setitem__
f1['age'] = 18
#执行def __delitem__
del f1['age']#del obj[key]时,我执行

#执行def __getitem__
f1['age1'] = 19
#执行__delattr__(self, item)
del f1.age1#del obj.key时,我执行

#给实例化对象添加属性
f1['name'] = 'alex'
print(f1.__dict__)#{'name': 'alex'}
  • 方法__call__

    • 对象后面加括号,触发执行

    • 注:构造方法的执行是由创建对象触发的

      • 即:对象 = 类名() ;

    • 而对于 __call__ 方法的执行是由对象后加括号触发的

      • 即:对象() 或者 类()()

class Foo:

    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')


obj = Foo()  # 执行 __init__
obj()  # 执行 __call__
  • 方法__iter__()

    • 迭代器

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1  # 初始化两个计数器a,b

    def __iter__(self):
        return self  # 实例本身就是迭代对象,故返回自己

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b  # 计算下一个值
        if self.a > 10:  # 退出循环的条件
            raise StopIteration()
        return self.a  # 返回下一个值


for i in Fib():
    print(i)
# 1
# 1
# 2
# 3
# 5
# 8
  • 方法isinstance()

    • 判断当前对象是否是某一个类的类型

#数据
print(isinstance("tom",str))#True
print(isinstance(4,str))#False

#类
class Person:
    ...

class Student(Person):
    ...

student = Student()
person = Person()

print(isinstance(student, Student))  # True
print(isinstance(person, Person))  # True
print(isinstance(person, Student))  # False
# 因为Person是Student父类,所以返回True
print(isinstance(student, Person))  # True
  • 方法issubclass()

    • 检验一个类是否属于另一个类的子类

class Person:
    ...

class Student(Person):
    ...

print(issubclass(Student, Person))  # True

【二】小总结(属性名,属性值)

  • 对象[属性名] = 属性值---》触发__setitem__方法

  • print(对象[对象])--->>触发了__getitem__方法

  • 对象.属性名 = 属性值---》>>触发__setattr__方法

  • 对象.对象 = 属性值 --- >>触发了__setattr__方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值