参考:https://www.cnblogs.com/nulige/p/6121079.html
魔法函数用于增强我们定义的类对象。在类对象中,以双下滑线开头以及结尾的成为魔法函数,比如常见的__init__。其实魔法函数就是Python类中具有特定功能的内置函数。通过魔法函数可以实现许多个性化、便捷的操作。
魔法函数可以随意定义某个类的特性,这些方法在进行特定的操作时会自动被调用。魔法函数不是通过继承等机制获得的,而是类一旦定义,Python内部机制自动会给类赋予这些特殊的函数,且用户是不能创建魔法函数的,即使函数名以双下划线开头和双下划线结尾。
魔法函数主要分为两大类:非数学运算和数学运算两大类。
一、常用非数学运算魔法函数:
__new__函数:在实例创建之前被调用的,它的任务就是创建实例,返回该实例。
__init__函数:当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。__new__在__init__之前被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,然后__init__给这个实例设置一些参数。
__dir__函数:默认返回类包含有所有属性名和方法名的有序列表,可重写__dir__(self)方法。
__repr__函数:默认返回属性(类名+object at+内存地址:<__main__.People object at 0x00000179FB2C1FA0>);可重写__repr__(self)方法。
__str__函数:默认不返回;当使用print输出对象的时候,只要重新__str__(self)方法,那么就会打印从在这个方法中return数据。
__iter__函数:返回一个迭代器对象。
__next__函数:返回迭代器的下个值,没有后续元素时会抛出一个StopIteration异常。
__call__函数:该方法的功能类似于在类中重载 () 运算符,使得类实例对象可以像调用普通函数那样,以“对象名()”的形式使用。
class People(): # def __new__(cls, *args, **kwargs): # if not hasattr(cls, '_inst'): # cls._inst = object.__new__(cls) # return cls._inst def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f"__repr__函数==》 {self.name} : {self.age}" def __str__(self): return f"__str__函数==》 {self.name} : {self.age}" def __call__(self,phone): print(f"__call__函数==》 {phone}") #自定义内置函数,用于排序(先名字升序,再年龄升序) def __lt__(self, item): return self.age < item.age if self.name == item.name else self.name < item.name if __name__ == "__main__": p1 = People("abc", 20) p1("15669910105") #__call__函数 print(p1) #__str__函数 print(p1.__dir__()) #__dir__函数 p2 = People("abc", 18) print(sorted([p1,p2])) #自定义__lt__函数
__iter__和__next__内置函数
# 自定义迭代器 class Range(): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self #__iter__函数 def __next__(self): if self.start > self.stop: raise StopIteration temp = self.start self.start += 1 return temp #__iter__函数 if __name__ == "__main__": ra = Range(1, 10) print(ra) #创建迭代器 print(next(ra)) #next()方法,可以记住位置 print(ra.__iter__()) #返回迭代器 print(ra.__next__()) #__next__()内置方法,可以记住位置
如果继承一个类,想初始化使用__init__内置函数,就必须先super(myThread).__init__()初始化父类,其他方法Thread.__init__(self)
from threading import Thread class myThread(Thread): def __init__(self): Thread.__init__(self) #方法1 class myThread(Thread): def __init__(self): super(myThread).__init__() #方法2
二、常用数学运算魔法函数:
float() #函数用于将整数和字符串转换成浮点数。
int() #函数用于将一个字符串或数字转换为整型。
round() #返回浮点数x的四舍五入值。
range() #返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以打印的时候不会打印列表。
list() #函数是对象迭代器,可以把range()返回的可迭代对象转为一个列表,返回的变量类型为列表。
all() #判断给定的可迭代参数iterable中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False。
any() #判断给定的可迭代参数 iterable 是否全部为 False,是则返回 False,如果有一个为 True,则返回 True。
三、其他相关介绍:
下划线
xx:公有变量。
_xx:前置单下划线,私有化属性或方法,一般来讲,变量名_xx被看作是“私有的”,在模块或类外不可以使用。但是类对象和子类可以访问,这并不能完全做到真正的私有,只是约定俗成的而已,这样写表示不希望这个变量在外部被直接调用。
__xx:前置双下划线,私有化属性或方法,无法在外部直接访问(名字重整所以访问不到,只能是允许这个类本身进行访问了。连子类也不可以)
__xx__:前后双下划线,系统定义名字(这就是在python中强大的魔法函数),因为变量名__xxx__对Python 来说有特殊含义,对于普通的变量应当避免这种命名风格。
xx_:后置单下划线,用于避免与Python关键词的冲突。
class Test(): def __init__(self): self.x = 'a' self._x = 'b' self.__x = 'c' if __name__ == '__main__': t = Test() print(f'x: {t.x}') print(f'_x: {t._x}') print(f'__x: {t.__x}') #不能被访问到
我在test类中定义了x,_x和 __x三个属性,并创建了test的类对象t,对这三个属性进行访问,__x不能被访问到。
__name__ == '__main__'
if __name__ == '__main__'的意思是:程序入口
当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;
当.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。