Python之路,第十八篇:Python入门与基础18
python3 面向对象编程2
类方法:
@classmethod
作用:1,类方法是只能访问类变量的方法;
2,类方法需要使用@classmethod 装饰器定义;
3,类方法的第一个参数是类的实例, 约定写成cls
说明:1, 类实例和对象实例都可以调用类方法;
2, 类方法不能方法实例变量
类方法和实例方法对比:
1,类方法能够访问类变量,不能访问实例变量;
实例方法能够访问类变量,也能访问实例变量
2,类方法可以用实例来调用,也可以用类来调用;
实例方法在调用时必须传入实例;
1 class Bank: 2 moneys = 10000000 #一千万 3 @classmethod 4 def total_money(cls): 5 print("某银行总行资金数:", cls.moneys) 6 7 def __init__(self, b): 8 self.branch = b 9 self.moneys = 5000000 10 self.__class__.moneys -= 5000000 11 12 13 Bank.total_money() #某银行总行资金数: 10000000 14 b1 = Bank("xxx地址支行") 15 b1.total_money() #某银行总行资金数: 5000000
静态方法
@staticmethod
作用:1, 静态方法是普通的函数;
2,静态方法定义在类的内部,只能凭借该类和实例调用
3,静态方法需要使用@staticmethod 装饰器定义
4,静态方法与普通函数定义相同,不需要传入self实例参数和cls类参数;
说明:1, 类实例和对象实例都可以调用静态方法;
2, 静态方法不能访问类变量和实例变量;
1 class A: 2 @staticmethod 3 def myadd(a, b): 4 return a + b 5 6 7 print(A.myadd(100, 200)) #300 8 a = A() 9 print(a.myadd(200, 300)) #500
实例方法,类方法,静态方法总结:
不想访问类变量的实例变量(属性),用静态方法;
只想访问类内变量,不想访问实例属性用类方法;
既想访问类内变量,也想访问实例变量用实例方法;
特性属性
@property 用来模拟一个属性;
通过@property 装饰器可以对模拟属性赋值和取值加以控制失效其他语言所拥有的getter 和 setter 功能;
1 import math 2 3 class Circle: 4 5 def __init__(self,r): #圆类 6 self.radius = r #半径 7 8 @property 9 def area(self): #面积 10 print("area函数被调用。。。") 11 return math.pi * self.radius ** 2 12 13 def area(self, a): #a代表面积 14 self.radius = math.sqrt(a/math.pi) 15 16 17 c1 = Circle(10) 18 print(c1.area) 19 #area函数被调用。。。 20 #314.1592653589793 21 c1.area = 31415.926 22 print(c1.radius) 23 print(c1.area) 24 #<bound method Circle.area of <__main__.Circle object at 0x00000000021ABB00>> 25 #10 26 #31415.926
函数 id
id(obj) 返回对象的标识(identity);
例: id(a) == id(a1) #F
1 >>> class A: 2 pass 3 4 >>> a = A() 5 >>> a1 = A() 6 >>> a is a1 7 False 8 >>> id(a) 9 54961992 10 >>> id(a1) 11 54905488 12 >>> a 13 <__main__.A object at 0x000000000346A748> 14 >>> 0x000000000346A748 15 54961992 16 >>>
运算符重载
什么是运算符重载?
用自定义的规则实现实例之间的运算符操作或函数操作;
作用:
1, 让实例像数学表达式一样的进行运算操作;
2, 让实例像内建对象一样函数操作;
3, 让程序简洁起来;
对象转字符串函数重载方法;
repr() 函数的重载方法:
def __repr__(self):
.....
str( ) 函数的重载方法:
def __str__(str):
....
注: 如果对象没有__str__方法, 则用repr(obj)函数的结果代替;
1 class MyNumber: 2 "此类用于定义一个整型数字类,用于演示str函数重载" 3 def __init__(self,v): 4 self.data = v 5 6 def __repr__(self): 7 print("__repr__被调用") 8 return "MyNumber(" + repr(self.data) + ")" 9 10 def __str__(self): 11 print("__str__被调用") 12 return "整数数值(" + str(self.data) + ")" 13 14 15 n1 = MyNumber(100) 16 n2 = MyNumber(200) 17 print(repr(n1)) 18 print(str(n2)) 19 #__repr__被调用 20 #MyNumber(100) 21 #__str__被调用 22 #整数数值(200) 23 print(n2) #等同于print(str(n2)) 24 #__str__被调用 25 #整数数值(200) 26 print(n1,(1,2,3),2j) 27 #__str__被调用 28 #整数数值(100) (1, 2, 3) 2j
算数运算符的重载:
+ __add__
- __sub__
* __mul__
/ __truediv__
// __floordiv__
% __mod__
** __pow__
二元运算符的重载的格式;
def __xxx__(self, other):
....
注: 二元运算符的重载方法的参数列表找中只能有两个参数;
重载说明: 运算符重载的方法参数已经有固定的含义,不可改变原有意义,除 __call__方法之外,其他重载方法的参数个数不可改变;
练习1: 自定义两个列表类;
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def infos(self): 7 return "MyList(" + str(self.data) + ")" 8 9 def __str__(self): 10 return self.infos() 11 12 13 L = [1,2,3] 14 L1 = MyList(L) 15 #L[2] = 3.14 16 print(L1.infos()) #MyList([1, 2, 3]) 17 print(L1) #MyList([1, 2, 3]) 18 L2 = MyList([4,5,6]) 19 print(L2.infos()) #MyList([4, 5, 6]) 20 print(L2) #MyList([4, 5, 6])
练习2: 实现两个类相加;
1 #自定义两个列表类,实现两个列表类相加 2 class MyList: 3 4 def __init__(self, a): 5 self.data = a.copy() 6 7 def infos(self): 8 return "MyList(" + str(self.data) + ")" 9 10 def __str__(self): 11 return self.infos() 12 13 def myadd(self,other): 14 r = [] 15 r.extend(self.data) 16 r.extend(other.data) 17 #self.data.clear() #L1 = MyList([]) 18 #other.data.clear() #L2 = MyList([]) 19 return MyList(r) 20 21 22 L1 = MyList([1,2,3]) 23 L2 = MyList([4,5,6]) 24 L3 = L1.myadd(L2) 25 print("L1=",L1) 26 print("L2=",L2) 27 #L3 = L1 + L2 28 print(L3) #MyList([1, 2, 3, 4, 5, 6])
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def infos(self): 7 return "MyList(" + str(self.data) + ")" 8 9 def __str__(self): 10 return self.infos() 11 12 def myadd(self,other): 13 r = [] 14 r.extend(self.data) 15 r.extend(other.data) 16 #self.data.clear() #L1 = MyList([]) 17 #other.data.clear() #L2 = MyList([]) 18 return MyList(r) 19 20 def __add__(self, other): 21 return self.myadd(other) 22 23 24 L1 = MyList([1,2,3]) 25 L2 = MyList([4,5,6]) 26 #L3 = L1.myadd(L2) 27 L3 = L1 + L2 28 print("L1=",L1) 29 print("L2=",L2) 30 print(L3) #MyList([1, 2, 3, 4, 5, 6])
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def infos(self): 7 return "MyList(" + str(self.data) + ")" 8 9 def __str__(self): 10 return self.infos() 11 12 def myadd(self,other): 13 r = [] 14 r.extend(self.data) 15 if type(other) == int: 16 r.append(other) 17 elif type(other) == MyList: 18 r.extend(other.data) 19 else: 20 raise ValueError("other 不能出现其他值") 21 #self.data.clear() #L1 = MyList([]) 22 #other.data.clear() #L2 = MyList([]) 23 return MyList(r) 24 25 def __add__(self, other): 26 return self.myadd(other) 27 28 29 L1 = MyList([1,2,3]) 30 L2 = MyList([4,5,6]) 31 #L3 = L1.myadd(L2) 32 L3 = L1 + L2 33 print("L1=",L1) 34 print("L2=",L2) 35 print(L3) #MyList([1, 2, 3, 4, 5, 6]) 36 L3 = L1 + 10 #追加一个值 37 print(L3) #MyList([1, 2, 3, 10])
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def infos(self): 7 return "MyList(" + str(self.data) + ")" 8 9 def __str__(self): 10 return self.infos() 11 12 #def myadd(self,other): 13 # r = [] 14 # r.extend(self.data) 15 # if type(other) == int: 16 # r.append(other) 17 # elif type(other) == MyList: 18 # r.extend(other.data) 19 # else: 20 # raise ValueError("other 不能出现其他值") 21 # #self.data.clear() #L1 = MyList([]) 22 # #other.data.clear() #L2 = MyList([]) 23 # return MyList(r) 24 25 def __add__(self, other): 26 return self.myadd(other) 27 28 def __mul__(self, rhs): #right hand side 29 return MyList(self.data * rhs) 30 #以下方法可以实现 31 #L0 = MyList([]) 32 #for x in range(rhs): 33 # L0 += MyList(self.data) 34 #return L0 35 36 L1 = MyList([1,2,3]) 37 L2 = MyList([4,5,6]) 38 L3 = L1 * 3 39 print(L3) #MyList([1, 2, 3, 1, 2, 3, 1, 2, 3])
反向算数运算符重载;
+ __radd__ (self, lhs) # 加法 lhs + self
- __rsub__(self, lhs) # 减法 lhs - self
* __rmul__(self, lhs) # 乘法 lhs * self
/ __rtruediv__(self, lhs) # 除法 lhs / self
// __rfloordiv__(self, lhs) #地板除 lhs // self
% __rmod__(self, lhs) #求余(取模) lhs % self
** __rpow__(self, lhs) #幂 lhs ** self
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def __str__(self): 7 return "MyList("+ str(self.data) +")" 8 9 def __mul__(self, rhs): #right hand side 10 return MyList(self.data * rhs) 11 12 def __rmul__(self, lhs): #左 13 #return MyList(self.data * lhs) 14 #return self * lhs 15 return self.__mul__(lhs) 16 17 18 L1 = MyList([1,2,3]) 19 L2 = MyList([4,5,6]) 20 L3 = 3 * L1 21 print(L3) #MyList([1, 2, 3, 1, 2, 3, 1, 2, 3])
复合赋值运算符:
__iadd__(self, rhs) #加法 self += rhs
__isub__(self, rhs) #减法 self -= rhs
__imul__(self, rhs) #乘法 self *= rhs
__itruediv__(self, rhs) #除法 self /= rhs
__ifloordiv__(self, rhs) #地板除 self /= rhs
__imod__(self, rhs) #取模(求余) self %= rhs
__ipow__(self, rhs) #幂 self **= rhs
1 class MyList: 2 def __init__(self,a): 3 self.data = a.copy() 4 5 def __str__(self): 6 return "MyList("+ str(self.data) +")" 7 8 def __mul__(self, rhs): #right hand side 9 print("__mul__") 10 return MyList(self.data * rhs) 11 12 def __imul__(self, rhs): 13 print("__imul__") 14 self.data = self.data * rhs 15 return self 16 17 L1 = MyList([1,2,3]) 18 L1 *= 2 19 print(L1) 20 #__mul__ 21 #MyList([1, 2, 3, 1, 2, 3])
一元运算符的重载:
__neg__ -(负号)
__pos__ +(正号)
__invert__ ~(取反)
重载方法:
def __xxx__(self):
....
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def __str__(self): 7 return "MyList("+ str(self.data) +")" 8 9 def __neg__(self): 10 ml = MyList(self.data) 11 for i in range(len(ml.data)): 12 ml.data[i] = -ml.data[i] 13 return ml 14 15 16 L1 = MyList([1,2,3]) 17 L3 = -L1 18 print(L3) #MyList([-1, -2, -3])
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def __str__(self): 7 return "MyList("+ str(self.data) +")" 8 9 def __invert__(self): 10 ml = MyList(self.data) 11 ml.data.reverse() 12 return ml 13 14 15 L1 = MyList([1,2,3]) 16 L3 = ~L1 17 print(L3) #MyList([3, 2, 1])
比较运算符的重载:
__lt__ < 小于
__le__ <=
__gt__ >
__ge__ >=
__eq__ ==
__ne__ !=
比较运算的通常用于返回True 和 False;
1 class Tree: 2 def __init__(self, h): #h 树的高度 3 self.height = h 4 5 def show(self): 6 "描述" 7 print(" * ") 8 print("***") 9 print(" * ") 10 print(" * ") 11 12 def __lt__(self, rhs): 13 print("__lt__") 14 return self.height < rhs.height 15 16 def __le__(self,rhs): 17 print("__le__") 18 return self.height < rhs.height 19 20 def __gt__(self, rhs): 21 return not (self <= rhs) 22 23 t1 = Tree(5) 24 t2 = Tree(10) 25 if t1 < t2: 26 print("t2树高") 27 else: 28 print("t1树高") 29 print(t1 <= t2) 30 print(t1 > t2)
位运算符重载
__invert__ ~取反
__and__ &位与
__or__ | 位或
__xor__ ^ 位异或
__lshift__ << 左移
__rshift__ >> 右移
内建函数的重载:
__abs__ abs(obj) 函数调用
__len__ len(obj)
__reversed__ reversed(obj)
__round__ round(obj)
1 class MyList: 2 3 def __init__(self, a): 4 self.data = a.copy() 5 6 def __str__(self): 7 return "MyList("+ str(self.data) +")" 8 9 def __abs__(self): 10 temp = self.data.copy() #列表 11 for i in range(len(temp)): 12 if temp[i] < 0: 13 temp[i] = -temp[i] 14 return MyList(temp) 15 16 17 L1 = MyList([1,-2,3,-4]) 18 L2 = abs(L1) 19 print(L2) #MyList([1, 2, 3, 4])
repr() __repr__
str() _str__
__add__ self + other
__radd__ other + self
__iadd__ self += other