Python基础(二十一):面向对象“类”第四课——魔法方法

先划一下重点:python

  • 6个魔法方法;
  • 动态操做属性的4个函数;

魔法方法

魔法方法的简单介绍

  • 魔法方法的命名规则:方法名(先后各有2个下划线)。函数

  • 一般状况下,不会主动去调用魔法方法,而是在知足必定的条件下,会自动去调用魔法方法。3d

  • 经常使用的魔法方法有6个,分别是:new、del、str、repr、bytes、call,下面我为你们一一讲解。code

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方法。orm

假如,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方法了

结果以下:blog

del方法

在销毁对象的时候(对象指的是咱们本身建立的对象),会首先调用该方法。字符串

class Person:
    def __init__(self):
        print("__init__执行")
    # 在该方法中,能够执行一些清理工做
    def __del__(self):
        print("该对象已经被销毁")

p = Person() # 能够看出,由于没有对象销毁,因此不会调用该方法

结果以下:get

class Person:
    def __init__(self):
        print("__init__执行")
    def __del__(self):
        print("该对象已经被销毁")
p = Person()
del p

结果以下:input

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()
print(p)

结果以下:

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解释器更相近

结果以下:

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))

结果以下:

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()

结果以下:

动态操做属性的4个函数

这4个函数分别是:hasattr、getattr、delattr、setattr,下面咱们一一来说述。

hasattr(参数1,参数2)

  • 第一个参数 :对象;
  • 第二个参数 :属性名;
  • 含义:判断某个对象,是否存在指定的属性名。若是存在,返回True,不然,返回False;
class Person():
    pass
    
p = Person()
print(hasattr(p,"name"))
p.name = "3417"
print(hasattr(p,"name"))

结果以下:

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","没有属性返回的默认值"))

结果以下:

setattr(参数1,参数2,参数3)

  • 第一个参数:对象;
  • 第二个参数:属性名;
  • 第三个参数:属性值;
  • setattr(p,"age",20) 至关于 p.age = 20;
class Person():
    pass
    
p = Person()
setattr(p,"age",20)
print(p.age)

结果以下:

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("请输入属性值:")
setattr(p, unknown, value)
print(getattr(p, unknown))

结果以下:

相关文章
相关标签/搜索