Python 中内置的特定的方法, 这些方法在进行特定的操作时,会自动被调用。
__init__(self, [ ]) # 类的构造函数, 用于初始化实例变量 不允许做任何形式的return
__new__(cls, [ ]) # 类的内置方法 对象实例化过程中第一个被调用的方法
由于__init__()方法不能够返回一个非None的值,因此在实例化对象时不能够通过该方法对不可变对象(str、tuple)进行改变,此使可以重写__new__()方法,在__new__()方法中对不可变对象进行处理,返回需要的结果。
(构造方法__init__() 与 __new__())
1 class A(str): 2 def __init__(self, string): 3 super().__init__() 4 # 在 __init__()中 即使对 string 进行操作也不能够返回一个有效的值 5 6 def __new__(cls,string): 7 string = string.upper() 8 return str.__new__(cls, string) 9 #能够返回值10 11 a = A('yi jing beng pan le ')12 print(a)13 14 ###################################315 YI JING BENG PAN LE
__del__(self) # 当对象的引用为 0 时调用 该方法, 并不是del 时调用该方法 (析构方法)
示例代码如下,这是在IDLE中运行的结果,但是在jupyter notebook中运行的结果并不相同 在第二次实例化对象时仍然调用了 该方法。。。。。。。。。。
1 >>> class A(): 2 def __init__(self): 3 print('nothing') 4 def __del__(self): 5 print('del BIF 被调用了') 6 7 8 >>> a = A() 9 nothing10 >>> b = a11 >>> del a12 >>> del b13 del BIF 被调用了14 >>>
工厂函数:
工厂函数即是类对象,在调用该函数时会生成一个实例对象。
算术运算的 内置方法。对象可以进行算术运算,可通过修改这些方法,改变对象的行为
重写__add__()方法,要避免在算术运算方法中加入算术运算方法,避免出现无限递归的调用
1 >>> class new_int(int):2 def __add__(self, x):3 return int.__sub__(self, x)4 5 6 >>> a = new_int(10)7 >>> b = new_int(12)8 >>> a + b9 -2
以下两种方式的区别:在try_int(第8行)定义的__add__()方法中使用 int()工厂函数进行了类型转换,由于工厂函数即是类对象的实例化,因此int(self)相当于重新实例化一个对象,进行加法操作,此时不会再调用c或d的__add__()方法。因此不会出现递归调用。
1 >>> class new_int(int): 2 def __add__(self, x): 3 return self + x 4 5 6 >>> class try_int(int): 7 def __add__(self, x): 8 return int(self) + int(x) 9 10 11 >>> a = new_int(10)12 >>> b = new_int(10)13 >>> a + b14 Traceback (most recent call last):15 File "", line 1, in 16 a + b17 File " ", line 3, in __add__18 return self + x19 File " ", line 3, in __add__20 return self + x21 File " ", line 3, in __add__22 return self + x23 [Previous line repeated 991 more times]24 RecursionError: maximum recursion depth exceeded25 >>> c = try_int(10)26 >>> d = try_int(10)27 >>> c + d28 2029 >>>
反运算符的变量顺序。
__str__() 与 __repr__()方法:
__str__():当需要打印输出对象时(print(object)),调用的方法。__repr__()直接输入对象名称返回值。
1 class test(): 2 def start(self): 3 self.start = 10 4 5 t = test() 6 t.start() 7 t.start() 8 9 ######################################10 ---------------------------------------------------------------------------11 TypeError Traceback (most recent call last)12in 13 5 t = test()14 6 t.start()15 ----> 7 t.start()16 17 TypeError: 'int' object is not callable
再一次强调,属性名与方法名重复会发生覆盖现象。请注意只有第七行报错:TypeError,原因时再第六行执行代码后会产生 第三行的同名变量,而后定义的变量会覆盖方法。
定义一个定时器的类,并通过重载其内部方法实现,定时器开始,结束,结果显示,及定时器对象的 加 (+,将两个定时器的时间相加并显示)操作。
需要注意,三个类方法在实例化后的调用顺序,如在start() 调用之前调用 stop()、未调用stop()而调用 + 操作,通过实例变量 message,对当前操作进度进行记录,并通过对时间的判断进行错误提醒,有点类似于状态机的状态码。
# 通过重定义内置方法 定制类import datetimeclass Mytimer(): num = 0 def __init__(self): self.__class__.num += 1 self.start_time = 0 self.stop_time = 0 self.time_sec = 0 self.message = '未开始计时!' # 重定义 __str__ 以及 __repr__内置函数 用于控制输出 def __str__(self): return self.message __repr__ = __str__ def __add__(self, time): if self.time_sec and time.time_sec: add_result = self.time_sec + time.time_sec self.message = '总共计时时间为:' + str(add_result) else: self.message = '计时未结束!' return self.message def start(self): self.start_time = datetime.datetime.now() print('计时开始!') self.message = '未结束计时!' def stop(self): if self.start_time: self.stop_time = datetime.datetime.now() delta_time = self.stop_time - self.start_time self.time_sec = delta_time.total_seconds() self.message = '计时结果为:' + str(self.time_sec) +'S' print('计时结束!') else: print('Plz run start first!')t = Mytimer()t1 = Mytimer()
定义类方法时需要注意实例变量与 函数的局部变量的区别,由于函数的局部变量生存空间仅限于该函数内部,因此需要在函数之间调用的变量需要设置未实例变量。实例变量与类变量之间由于作用对象不同,相互没有影响,类变量用于描述这个抽象类的属性,而实例变量用于描述实例化对象的属性。注意实例变量名与方法名不能相同,否则在__init__()初始化后会导致与变量名相同的函数被覆盖。
。