Python系列:面向对象“类”之魔法方法
今天就带着大家开始我们——Python学习的第二课,Python基础之魔法方法(4)。
这一节的知识有点难,大家一定好好消化,不要轻易放弃。这里我想带着大家学习以下知识:
- 6个魔法方法;
- 动态操作属性的4个函数;
1. 魔法方法
1.1 魔法方法的简单介绍
魔法方法的命名规则:方法名(前后各有2个下划线)。
通常情况下,不会主动去调用魔法方法,而是在满足一定的条件下,会自动去调用魔法方法。
常用的魔法方法有6个,分别是:new、del、str、repr、bytes、call,下面我为大家一一讲解。
1.2 new方法
- 注意1 : 在创建对象的时候,会首先调用该方法,init方法还是在 new方法之后被调用;
- 注意2 : 一个不需要@classmethod修饰的类方法;
- 注意3 : 我们只需要知道,在创建对象的时候,new方法比init方法,先调用即可。平时没怎么用它;
class Person:
# __new__不用@classmethod修饰的一个类方法
# 在创建对象的时候,会首先调用该方法
# 如果在该方法中,返回当前类的对象(也即创建对象),接下来会调用__init__方法,对对象进行初始化。否则,__init__方法不会得到执行
def __new__(cls):
return super().__new__(cls) # 这行代码是创建对象,只是我现在不太明白
Person() # 在我们写类的时候,不需要写这个。这里讲述一下,只是想让我们知道。在创建对象的时候,__new__方法比__init__方法,先调用
若一个类中既有new方法,也有init方法,当我们创建对象时候,首先执行new方法。
假如,new方法中没有return super().new(cls) ,则不会执行init方法。写上以后,表示再次创建一个对象才会执行init方法。
# 第一段代码
class Person:
def __new__(cls):
print("__new__执行")
return super().__new__(cls) # 这行代码是创建对象,只是我现在不太明白
def __init__(self):
print("__init__执行")
p = Person()
# 第二段代码
class Person:
def __new__(cls):
print("__new__执行")
#return super().__new__(cls) # 假如不返回,当前类的对象,__init__就不会执行
def __init__(self):
print("__init__执行")
p = Person() # 因为,这里创建的对象,先去执行new方法了
结果如下:
1.3 del方法
在销毁对象的时候(对象指的是我们自己创建的对象),会首先调用该方法。
class Person:
def __init__(self):
print("__init__执行")
# 在该方法中,可以执行一些清理工作
def __del__(self):
print("该对象已经被销毁")
p = Person() # 可以看出,因为没有对象销毁,所以不会调用该方法
结果如下:
class Person:
def __init__(self):
print("__init__执行")
def __del__(self):
print("该对象已经被销毁")
p = Person()
del p
结果如下:
1.4 str方法
- 注意1 : 该方法在使用内建函数(str,format,print)的时候,会自动调用;
- 注意2 : 该方法末尾,需要返回一个str类型的对象;
class Person:
def __new__(cls):
print("__new__执行")
return super().__new__(cls)
def __init__(self):
print("__init__执行")
def __del__(self):
print("该对象已经被销毁")
# 在使用内建函数(str,format,print)的时候,会自动调用该方法
# 该方法需要返回一个str类型的对象
# def __str__(self):
# return "Person类型的对象"
p = Person()
print(p)
结果如下:
class Person:
def __new__(cls):
print("__new__执行")
return super().__new__(cls)
def __init__(self):
print("__init__执行")
# 在使用内建函数(str,format,print)的时候,会自动调用该方法
# 该方法需要返回一个str类型的对象
def __str__(self):
return "Person类型的对象"
p = Person()
p
结果如下:
class Person:
def __new__(cls):
print("__new__执行")
return super().__new__(cls)
def __init__(self):
print("__init__执行")
# 在使用内建函数(str,format,print)的时候,会自动调用该方法
# 该方法需要返回一个str类型的对象
def __str__(self):
return "Person类型的对象"
p = Person()
str(p)
结果如下:
1.5 repr方法
- 注意1 :该方法在使用内建函数(repr)的时候,会自动调用;
- 注意2 :该方法也需要返回一个str类型的对象;
class Person:
def __new__(cls):
print("__new__执行")
return super().__new__(cls)
def __init__(self):
print("__init__执行")
def __del__(self):
print("该对象已经被销毁")
def __str__(self):
return "Person类型的对象"
# __str__ 与 __repr__ 的区别:二者都是返回对象的字符串表示。
# 不同的是:__str__ 返回的通常是让人容易阅读的格式。__repr__返回的是面向Python解释器的,通常格式:<内容>
def __repr__(self):
return "<Person class>"
p = Person()
print(str("abc")) # 结果是abc,这个更加接近人阅读模式
print(repr("abc")) # 结果是'abc',字符串本来就是带引号的,所以这个和python解释器更相近
结果如下:
1.6 bytes方法
该方法在使用内建函数(bytes)的时候,会自动调用.
class Person:
def __new__(cls):
print("__new__执行")
return super().__new__(cls)
def __init__(self):
print("__init__执行")
def __del__(self):
print("该对象已经被销毁")
def __str__(self):
return "Person类型的对象"
def __repr__(self):
return "<Person class>"
def __bytes__(self):
return b"byte person class"
p = Person()
print(bytes(p))
结果如下:
1.7 call方法
把对象当成函数来使用的时候,会自动调用。
class Person:
def __new__(cls):
print("__new__执行")
return super().__new__(cls)
def __init__(self):
print("__init__执行")
def __del__(self):
print("该对象已经被销毁")
def __str__(self):
return "Person类型的对象"
def __repr__(self):
return "<Person class>"
def __bytes__(self):
return b"byte person class"
# 把对象当成函数来使用的时候,会自动调用该方法
def __call__(self):
print("把对象当成函数来使用的时候")
p = Person()
p()
结果如下:
2. 动态操作属性的4个函数
这4个函数分别是:hasattr、getattr、delattr、setattr,下面我们一一来讲述。
2.1 hasattr(参数1,参数2)
- 第一个参数 :对象;
- 第二个参数 :属性名;
- 含义:判断某个对象,是否存在指定的属性名。如果存在,返回True,否则,返回False;
class Person():
pass
p = Person()
print(hasattr(p,"name"))
p.name = "郭卫华"
print(hasattr(p,"name"))
结果如下:
2.2 getattr(参数1,参数2,参数3)
- 第一个参数 :对象;
- 第二个参数 :属性名;
- 第三个参数 :当属性不存在时,返回默认值,这个默认值也是自己设置;
- 含义:返回对象对应的属性(第二个参数指定的属性)。传入2个参数,若不存在,则报错;穿入3个参数,若不存在,返回第三个参数设置的默认值;
class Person():
pass
p = Person()
print(getattr(p,"name"))
结果如下:
class Person():
pass
p = Person()
p.name = "郭卫华"
print(getattr(p,"name"))
结果如下:
class Person():
pass
p = Person()
print(getattr(p,"age","没有属性返回的默认值"))
结果如下:
2.3 setattr(参数1,参数2,参数3)
- 第一个参数: 对象;
- 第二个参数: 属性名;
- 第三个参数: 属性值;
- setattr(p,“age”,20) 相当于 p.age = 20;
class Person():
pass
p = Person()
setattr(p,"age",20)
p.age
结果如下:
2.4 delattr(参数1,参数2,参数3)
- 第一个参数: 对象;
- 第二个参数: 属性名;
- delattr(p,“name”) 相当于 del p.name;
class Person():
pass
p = Person()
setattr(p,"age",20)
delattr(p,"age")
print(hasattr(p,"age"))
结果如下:
注意1 : 动态操作属性没有直接操作属性简便,但是比直接访问属性灵活。
注意2 :直接访问属性必须在写代码时,就需要知道属性的名字,而动态操作属性没有此限制(这在其他语言中叫做’“反射”)。
class Person():
pass
p = Person()
unknown = input("请输入属性名:")
value = input("quit输入属性值:")
setattr(p,unknown,value)
getattr(p,unknown)
结果如下:
- 点赞
- 收藏
- 关注作者
评论(0)