python 魔术方法

1、__repr__函数

  • 通常__repr__函数是应用于实例化类中
  • print(实例化类),直接打印出对应函数返回值
  • 没有自定义__str__函数时,str(实例化类) 可以调用__repr__
  • repr(实例化类),调用__repr__
class A:
    def __repr__(self):
        # print("哈哈哈")
        return "输出repr"

B = A()
C = repr(B)
print(C)
# 输出repr

C1 = str(B)
print(C1)
# 输出repr

print(B)
# 输出repr

2、__str__函数

  • 同时定义__repr__和__str__,print(实例化类) 时,调用的是__str__方法
  • __str__可以被str(实例化类)调用,不能被repr(实例化类)函数调用
class A:
    def __repr__(self):
        return "输出repr"

    def __str__(self):
        return "输出str"

B = A()

C1 = str(B)
print(C1)
# 输出str

print(B)
# 输出str

3、__iter__函数 和__next__函数

  • __iter__和__next__一般用于共同实现一个迭代器
  • __iter__的作用主要是先变成一个迭代器对象,调用下一个元素是调用__next__的函数,当是最后一个函数时,必须抛出StopIteration来结束迭代
  • __iter__加yield 也可以生成一个迭代器来迭代
__iter__ 加 __next__
class A:
    def __iter__(self):
        self.a = 0
        return self

    def __next__(self):
        self.a += 1
        if self.a > 10:
            raise StopIteration
        return self.a

B =  A()
for i in B:
    print(i)

1
2
3
4
5
6
7
8
9
10

__iter__ 加 yield
class A:
    def __init__(self):
        self.field = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    def __iter__(self):
        for f in self.field:
            yield f

   
B = A()
for i in B:
    print(i)

1
2
3
4
5
6
7
8
9
10



4、__getitem__函数

  • 让类可以像字典一样访问
class A:
    def __init__(self):
        self.field = {"name": "张三", "age": 18}

    def __getitem__(self, key):
        return self.field[key]


B = A()
print(B["age"])
18
print(B["name"])
张三

  • 构建可迭代对象,用for循环调用时,自动调用__getitem__并且传入index
class A:
    def __init__(self):
        self.field = ['yi', 'er', 'san']

    def __getitem__(self, index):
        return self.field[index]

B = A()
for i in B:
    print(i)

5 module/doc/name 魔术函数

  • doc 打印出三元注释信息
  • name 当前对象的名称
  • module 当前对象属于那个模块,如果属于执行文件,那么结果是__main__ 否则就是所在的文件名称命名
class A:
    "测试类"
    pass

print(A.__doc__)
测试类
print(A.__name__)
A
print(A.__module__)
__main__

两个文件示例

  • 当执行test.py文件时,可以发现导入te11时,就执行te11.py文件
  • 此时A.__name__显示的便是te11文件名称

te11.py

class A:
    "测试类"
    pass

print(A.__doc__)
print(A.__name__)
print(A.__module__)

test.py

from te11 import *

import sys

print(sys.modules[__name__], 'apps')
print(hasattr(sys.modules[__name__], "apps"))

测试类
A
te11
<module '__main__' from 'D:/projectdir/ForwardPro/test.py'> apps
False

6、__getattr__函数

  • 调用对象没有的属性时,会触发__getattr__函数
class A:
    def __init__(self):
        self.name = '张三'
        self.money = 19
   # 调用不存在的属性,属性会传参到__getattr__,item就是没有的属性名称
   # 比如当调用B.age时,item就是age
    def __getattr__(self, item):
        print(item)
        return 10


B = A()
 
print(B.age)
print(B.name)
print(B.money)

age
10
张三
19


7、__getattribute__函数

  • 如果自定义了 getattribute,调用对象的属性都会走__getattrubute__这个函数,而不会管真实的属性值是什么
class A:
    def __init__(self):
        self.name = '张三'
        self.money = 19

    def __getattribute__(self, item):
        print(f'{item}')
        return f"{item}-01"
B = A()
print(B.age)
print(B.name)
print(B.money)

age
age-01
name
name-01
money
money-01

8 new/init/call 魔术方法

  • new 通常在实例化类时,先走__new__方法,创建新的内存对象
  • init 实例化类时,走完__new__方法,需要走__init__方法,初始化参数
  • call 实例对象 后面加括号时,会调用其类的__call__方法
class A:
    def __init__(self):
        print("2、再来初始化")
        self.name = '张三'
        self.money = 19
   # 因为new是创建的实例对象,所以输入的不应该是self代表实例对象
   # 应该输入cls 表示A类
    def __new__(cls):
        print(id(cls))
        print(cls.__name__)
        print("1、先创建对象")
        obj = super().__new__(cls)
        print(id(obj))
        return obj

    def __call__(self):
        print(id(self))
        print("调用__call__方法")
B = A()
print(B.name)
print(id(B))
B()

1966830241088
A
1、先创建对象
1966290785856
2、再来初始化
张三
1966290785856
1966290785856
调用__call__方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值