python魔法方法

在学习面向对象的时候,我们知道在 python 中有一类特殊的方法,叫做魔法方法,这种方法的特点如下:

  1. 方法定义的时候以两个下划线开头和两个下划线结尾:如__init____str____repr__
  2. 这类方法一般不需要我们手动调用,在满足某个条件的时候会自动调用,这个满足的条件我们可以成为调用时机

__str__()方法

这个类方法(str())主要的作用是在print(实例)的时候返回你指定的字符串,一般来说在定义类的时候不用重写这个方法的,但是在一些注重交互的模块类的编写上,可能会重写这个类。下面直接进入例子。

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

接下来我们实例化这个类,并打印这个实例。

A = Car('BNW')
print(A)

我们一般就能看到这样的结果:
<__main__.Car object at 0x000002B249DD4E20>
这个结果主要是告诉我们这个A是哪一个类(Car类),还有所在内存位置(0x000002B249DD4E20)
下面我们在Car类中重写__str__方法,再打印这个A,看看会有什么差别。

class Car():
def __init__(self, name):
self.name = name
def __str__(self) -> str:
text = f'这是一辆车,名字是{self.name}'
return text
A = Car('BNW')
print(A)
这是一辆车,名字是BNW

可以看到,这个时候print(实例),将会出现我们指定好的str内容。这就是__str__()方法的用处,不过要注意,这个方法必须要保证返回的是一个str。

对一个对象打印时,自动执行 str 方法

class A:
def __init__(self, name, age):
self.name = name
self.age = age
self.sex = "男"
def __str__(self):
print(555)
return "abc"
a1 = A("尘世风", 18)
# 对一个对象打印时,自动执行 __str__ 方法
print(a1)
# 运行结果:
# 555
# abc

__len__()方法

len()可以检测对象中某个数据得信息,只有一个参数self,用于接收当前对象,它必须有返回值,返回值必须是整数;
当我们不使用__len__()方法检测对象时,会报TypeError: object of type ‘UseLen’ has no len()错误

class UseLen(object):
def __init__(self, age):
self.age = age
self.li = ['a', 'v', 's']
U = UseLen(12)
print(len(U))
Traceback (most recent call last):
File "D:\code\xmczapitest\test.py", line 7, in <module>
print(len(U))
TypeError: object of type 'UseLen' has no len()

当我们使用__len__方法检测对象时,需要注意的是必须有返回值,方法中只有一个self参数

class UseLen(object):
def __init__(self, age):
self.age = age
self.li = ['a', 'v', 's']
def __len__(self):
return len(self.__dict__)
U = UseLen(12)
print(len(U)) # 2

__call__ 方法

__call__可以使得方法变成可被调用对象

class Foo:
def __init__(self):
print("实例化一个对象时自动执行 __init__ 方法")
def __call__(self, *args, **kwargs):
print('调用实例化对象时自动触发 __call__ 方法')
obj = Foo() # 实例化一个对象时自动执行 __init__ 方法
obj() # 调用实例化对象时自动触发 __call__ 方法

new() 方法

当Python实例化一个对象时,首先调用__new__()方法构造一个类的实例,并为其分配对应类型的内存空间,该实例的内存地址就是它的唯一标识符。然后再调用__init__()方法对实例进行初始化,通常是对该实例的属性进行初始化
以下用几个实例来说明:
实例1:先调用__new__()方法再调用__init__()方法

class Person(object):
def __new__(cls):
print("__new__ called")
return super().__new__(cls)
def __init__(self):
print("__init__ called")
a = Person()

结果

__new__ called
__init__ called

实例2:new()方法构造一个类实例,并将该实例传递给自身的__init__()方法,即__init__()方法的self参数。

class Person(object):
def __new__(cls):
print("__new__ called")
instance = super().__new__(cls)
print(type(instance))
print(instance)
print(id(instance))
return instance
def __init__(self):
print("__init__ called")
print(id(self))
b = Person()

结果

__new__ called
<class '__main__.Person'>
<__main__.Person object at 0x0000026D76844DC0>
2669163072960
__init__ called
2669163072960

实例3:如果__new__()方法不返回任何实例的话,init()方法将不会被调用。

class Person(object):
def __new__(cls):
print("__new__ called")
def __init__(self):
print("__init__ called")
c = Person()

结果:

__new__ called

实例4:如果__new__()方法返回一个其他类的实例的话,那它自身的__init__()方法将不会被调用。而且,new()方法将会初始化一个其他类的对象。

class Animal(object):
def __init__(self):
pass
class Person(object):
def __new__(cls):
print("__new__ called")
return Animal()
def __init__(self):
print("__init__ called")
d = Person()
print(type(d))
print(d)

结果:

__new__ called
<class '__main__.Animal'>
<__main__.Animal object at 0x0000022BDDEEF400>

实例5:如果重写__new__()方法时,除了cls参数外不再设置其他参数的话,将无法用__init__()方法来设置初始化参数。

class Person(object):
def __new__(cls):
print("__new__ called")
instance = super().__new__(cls)
return instance
def __init__(self, name):
print("__init__ called")
self.name = name
e = Person("Alice")
print(e.name) # TypeError: Person.__new__() takes 1 positional argument but 2 were given

实例6:在重写__new__()方法时,需要在参数中加入*args,**kwargs,或者显式地加入对应的参数,才能通过__init__()方法初始化参数。

class Person(object):
def __new__(cls, *args,**kwargs): # Or def __new__(cls, name)
print("__new__ called")
instance = super().__new__(cls)
return instance
def __init__(self, name):
print("__init__ called")
self.name = name
e = Person("Alice")
print(e.name)

结果:

__new__ called
__init__ called
Alice
posted @   尘世风  阅读(154)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
*/
点击右上角即可分享
微信分享提示

目录导航