资讯专栏INFORMATION COLUMN

经验拾忆(纯手工)=> Python__黑魔法__

tulayang / 997人阅读

摘要:类的继承类继承有三种调用方式,其实是有区别的,听我慢慢道来第一种父类方法参数直接调用第二种方法参数直接调用在谁的类下调用,就找此类对应的下一个就是要继承的第三种方法参数找类名对应的的下一个,就是继承的,一般写本身的类名上下文管理器上下文管理

类的继承
类继承有三种调用方式,其实是 有区别 的,听我慢慢道来
class A:
    def say(self, name):
        print(f"Im {name}")
class B(A):
    def say(self, name):
    # 第一种:父类.方法(self, 参数) 直接调用
        A.say(self, name)    
        
    def say(self, name):
    # 第二种:super().方法(参数)    直接调用
    # 在谁的类下调用super,就找此类对应 mro()的下一个,就是要继承的
         super().say(name)
         
    def say(self, name):
    # 第三种:super(B, self).方法(参数)
    # 找类名 对应的 mro()的下一个,就是 继承的,一般写本身的类名
        super(B, self).say(name)

B().say("Tom")
上下文管理器
"""
    上下文管理器可以用两种方式实现:
"""
     方式1:通过类来实现
        主要实现两种协议
            1. __enter__(self)
            2. __exit__(self, *args, **kwargs)
                
        class A():
            def __init__(self, name):
                self.name = name
            def __enter__(self):
                print("进入")
                return self
            def __exit__(self, *args, **kwargs):
                print("退出")
                return True
        
        with A("Tom") as a:
            print(a.name)

    方式2:通过函数来实现
        from contextlib import contextmanager
        @contextmanager
        def f():
            print("开始")    # yield 之前 对应 with f()
            yield "中间"     # yield 的值 就是    as 之后的值
            print("结束")    # yield 之后 对应 print(str1) 这个语句体
        
        with f() as str1:
            print(str1)
        ------------------Output----------------------
        开始
        中间
        结束
属性描述符-property-setter
class A:
@property
def name(self):
    return "123"
@name.setter
def name(self, value):
    self.age=value

a = A()
print(a.name)
a.name = "456"
print(a.age)


__init__()
实例化对象时自动调用,这里先卖个关子,见下面 __new__()
__call__()
"""
   对象当做函数执行的时候会自动调用 __call__()
"""
class A():
    pass
a = A()    # 此处自动调用了 __init__()
a()        # 此处自动调用了 __call__()
__str__()
"""
    对对象进行print操作的时候 会自动调用 __str__()
"""
class A:
    def __str__(self):
        return "5"
a = A()
print(a)  # 此处自动调用了 __str__()
__new__()
"""
    上面说过 __init__()是实例化对象的时候自动调用,在它之前还隐式调用了 __new__()
    __new__返回的是什么,对象就是什么
"""
In [2]: class A:
   ...:   def __new__(self):
   ...:     print("__new__")    # 初始化对象只调用 __new__ 而不调用 __init__
   ...:     return 1
   ...:   def __init__(self):
   ...:     print(2)
   ...: print(A())
    __new__
    1
__setattr__() 和 __getattr__() 和 __delattr__()
"""
    __setattr__():=号 属性赋值 会自动调用此方法 
    __getattr__():.号 属性取值 会自动调用此方法    # 注:找不到属性才会调用此方法
    __delattr__():del 属性删除 会自动调用此方法
"""
class A:

    def __init__(self, name):
        self.name = name        # 赋值操作就会调用 __setattr__()
    
    def __setattr__(self, name, value):
        print(f"{name}:{value}")
    def __getattr__(self, name):
        print(name)
    def __delattr__(self,name):
        print("del了")
        
a = A("Jack")    # 调用了 __init__
a.name = "Tom"   # 赋值操作再次调用 __setattr__()
a.name           # 取值操作调用 __getattr__()
---------------------output---------------------
name:Jack
name:Tom
name
del了
__getattribute__()
"""
    和 __getattr__() 一样,只不过 __getattribute__最先调用,并拦截了 __getattr__()
"""
class A:
    def __init__(self):
        self.name = 1
    def __getattr__(self,x,*args, **kwargs):
        print(456)
    def __getattribute__(self, x):
        print(123)

a = A()
a.aaaaaa
-----------output---------------
123
__getitem__()
"""
    对对象进行 切片、索引、遍历 等 会自动调用此方法
"""
class A:
def __getitem__(self,x,*args, **kwargs):
    return x

a = A()
触发方式1: 如果直接索引此对象,那么索引值就会传递到上面 x 当作参数
    print(a[5])
    >> 5
触发方式2: 如果直接切片此对象,那么slice对象 就会传递到上面 x 当作参数
    print(a[1:5])
    >> slice(1, 5, None)
触发方式3: 如果for循环迭代此对象,那么 上面的 x 每次将会被赋予从零开始 自增1的自然整数
    for x in a:
        print(x)
    >> 0,1,2,3,4.................... 
__init_subclass__()
"""
    被继承的类 会自动调用__init_subclass__ 
"""
class A:
    def __init_subclass__(self):
        print("我被继承了")

class B(A):
    pass
__base__()
"""
    查看基类
"""
class A:
    pass
class B(A):
    pass
print(B.__base__)
-----------output---------------
__contains__()
"""
    xx in xx 就会自动调用  __contains__()
"""

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43860.html

相关文章

  • 经验拾忆手工)=> Python三器

    摘要:也就是给原函数加个外壳。类装饰填充了啊我是原函数类装饰填充了啊我是原函数说明后面关于类的装饰器如果理解困难当做了解即可,用的也少。 可迭代对象、生成器、迭代器三者的关系 1. 迭代器一定是可迭代对象 2. 生成器是迭代器的一种 3. 可迭代对象:必须实现 __iter__方法 4. 迭代器:必须实现 __iter__方法 和 __next__ 方法 5. 生成器:必须实现 __it...

    Miracle_lihb 评论0 收藏0
  • 经验拾忆手工)=> Python三程

    摘要:多线程对于爬虫方面也可以表现出较好的性能。计算密集型就别想多线程了,一律多进程。所以同一时刻最大的并行线程数进程数的核数这条我的个人理解很模糊,参考吧多线程多线程有种通过的那种方式,非常普遍,此处就不写了。 GIL的理解 GIL这个话题至今也是个争议较多的,对于不用应用场景对线程的需求也就不同,说下我听过的优点: 1. 我没有用过其他语言的多线程,所以无法比较什么,但是对于I/O而言,...

    Snailclimb 评论0 收藏0
  • 经验拾忆手工)=> Python好用深度技能工具介绍

    摘要:单元素元祖这是整数这才是元祖也许这两行,你们当时疑惑过,并且现在也都知道了,当然重点并不在这里。。虽然我水平很垃圾,但是我知道匿名函数有一种执行方式叫做自执行。看吧,这就是版的匿名函数自执行方法。 单元素元祖: a = (1) # 这是整数1 a = (1,) # 这才是元祖 也许这两行,你们当时疑惑过,并且现在也都知道了,当然重点并不在这里。。 我无聊的时候想过,为什么单...

    UnixAgain 评论0 收藏0
  • 经验拾忆手工)=> Python高阶函数操作

    摘要:解释就相当于把每个序列元素的每一个单独用一个管道函数处理,再把他们按顺序组合成一个新可迭代对象注意这个管道函数只能是单参数函数,如果想传递多个参数怎么办使用偏函数怕有些人看不懂,这里就不用了,而是用普通函数定义方式固定值固定值固定值固定值固 map In [25]: list(map(lambda a:a**2, [1,2,3,4])) Out[25]: [1, 4, 9, 16] 解...

    Elle 评论0 收藏0
  • 经验拾忆手工)=> Python基本数据类型

    摘要:不要疑惑,告诉你答案这个代表正负号的正。虽然一点技术含量没有,但是你要懂序列也许叫可迭代对象更为合适,但是我喜欢叫序列。 数据结构 可变类型与不可变类型(重头戏) 基操: 可变类型:[], {} # 可增删改 查 不可变类型: int float str () # 无法增删改, 只可查 升操: + 与...

    Andrman 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<