python之路 -- 面向对象进阶

property、classmethod、staticmethod

1.property

把方法伪装成了属性

 1 from math import pi
 2 class Circle:
 3     def __init__(self,r):
 4         self.r = r
 5     @property        #把方法伪装成了属性
 6     def perimeter(self):
 7         return 2*pi*self.r
 8     @property
 9     def area(self):
10         return self.r**2*pi
11 
12 c1 = Circle(5)
13 print(c1.area)     
14 # 圆的面积   #之前的调用方法为c1.area()
15 print(c1.perimeter) 
16 # 圆的周长   #之前的调用方法为c1.perimter()
 1 #练习
 2 #BMI指数(BMI是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
 3 # 成年人的BMI数值
 4 # 过轻:低于18.5
 5 # 正常:18.5~23.9
 6 # 过重:24~27
 7 # 肥胖:28~32
 8 # 非常肥胖:28~32
 9 #     体质指数(BMI)=体重(kg)/身高^2(m)
10 #     例如:70kg÷(1.75*1.75)=22.86
11 
12 class People:
13     def __init__(self,name,high,weight):
14         self.name = name
15         self.high = high
16         self.weight = weight
17 
18     @property
19     def bmi(self):
20         return self.weight/self.high**2
21 
22 xiaoli = People("小黎",1.66,47)
23 print(xiaoli.bmi()) #未加@property时,用此调用
24 print(xiaoli.bmi)   #加了@property时,用此调用
练习
 1 class Goods:
 2     def __init__(self):
 3         # 原价
 4         self.original_price = 100
 5         # 折扣
 6         self.discount = 0.8
 7 
 8     @property
 9     def price(self):
10         # 实际价格 = 原价 * 折扣
11         new_price = self.original_price * self.discount
12         return new_price
13 
14     @price.setter    #使用了这个可以修改类中的属性
15     def price(self, value):
16         self.original_price = value
17 
18     @price.deleter
19     def price(self):
20         del self.original_price
21         print('已删除')
22 obj = Goods()
23 print(obj.price)  # 获取商品价格
24 obj.price = 100   # 修改商品原价
25 print(obj.price)
26 del obj.price     # 删除商品原价
27 #执行del,会调用deleter装饰的方法
28 
29 #执行结果为:
30 # 80.0
31 # 80.0
32 # 已删除
View Code

classmethod   类方法

把一个方法 变成一个类中的方法,这个方法就直接可以被类调用,不需要依托任何对象

1 class Classmethod_Demo():
2     role = 'dog'
3 
4     @classmethod
5     def func(cls):
6         print(cls.role)
7 
8 Classmethod_Demo.func()
9 #输出结果为:dog
 1 class Goods:
 2     __discount = 0.8
 3     def __init__(self,name,price):
 4         self.name = name
 5         self.__price = price
 6     @property
 7     def price(self):
 8         return self.__price * Goods.__discount
 9     @classmethod   
10     # 把一个方法 变成一个类中的方法,这个方法就直接可以被类调用,不需要依托任何对象
11     def change_discount(cls,new_discount):  # 修改折扣
12         cls.__discount = new_discount
13 apple = Goods('苹果',5)
14 print(apple.price)  #--》4.0
15 Goods.change_discount(0.5)   # Goods.change_discount(Goods)
16 print(apple.price)  #--》2.5
17 # 当这个方法的操作只涉及静态属性的时候 就应该使用classmethod来装饰这个方法
View Code

staticmathod 静态的方法

用staticmethod将这个函数变成一个静态方法

 1 class Login:
 2     def __init__(self,name,password):
 3         self.name = name
 4         self.pwd = password
 5     def login(self):pass
 6 
 7     @staticmethod
 8     def get_usr_pwd():   # 静态方法
 9         usr = input('用户名 :')
10         pwd = input('密码 :')
11         Login(usr,pwd)
12 
13 Login.get_usr_pwd()
14 # 在完全面向对象的程序中,
15 # 如果一个函数 既和对象没有关系 也和类没有关系 那么就用staticmethod将这个函数变成一个静态方法

# 类方法和静态方法 都是类调用的

# 对象可以调用类方法和静态方法。但是,一般情况下 推荐用类名调用

# 类方法 有一个默认参数 cls 代表这个类 cls

# 静态方法 没有默认的参数 就像函数一样


内置函数isinstance()和issubclass()

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

issubclass(sub, super)检查sub类是否是 super 类的子类

class A:pass
class B(A):pass
a = A()
print(isinstance(a,A)) ->True   #检查对象a是否是类A中的对象,是返回True
print(issubclass(B,A)) ->True   #检查类B是否是类A的子类
print(issubclass(A,B)) ->False

反射

python面向对象中的反射:通过字符串的形式操作对象相关的属性。

python中的一切事物都是对象(都可以使用反射)

面向对象中的几个内置函数

  ——hasattr,setattr,getattr,delattr

 1 class Foo:
 2     f = '类的静态变量'
 3     def __init__(self,name,age):
 4         self.name=name
 5         self.age=age
 6 
 7     def say_hi(self):
 8         print('hi,%s'%self.name)
 9 
10 obj=Foo('egon',73)
11 
12 #检测某个类是否含有某属性
13 print(hasattr(obj,'name'))    
14 print(hasattr(obj,'say_hi'))
15 
16 #获取某个类中的属性
17 #第一个位置为所属的对象,第二个为变量的字符串形式
18 n=getattr(obj,'name')    #等价于obj.name
19 print(n)
20 func=getattr(obj,'say_hi')
21 func()
22 
23 print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
24 
25 #设置属性
26 setattr(obj,'*名字*',True)
27 setattr(obj,'show_name',lambda self:self.name+'-名字')
28 print(obj.__dict__)
29 print(obj.show_name(obj))
30 
31 #删除属性
32 delattr(obj,'age')
33 delattr(obj,'show_name')
34 # delattr(obj,'show_name111')#不存在,报错
35 
36 print(obj.__dict__)
37 
38 输出结果为:
39 True
40 True
41 egon
42 hi,egon
43 不存在啊
44 {'name': 'egon', 'age': 73, '*名字*': True, 'show_name': <function <lambda> at 0x000002DBD32D2E18>}
45 egon-名字
46 {'name': 'egon', '*名字*': True}

__str__、__repr__

当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据 

 1 class Car:
 2     def __init__(self, newWheelNum, newColor):
 3         self.wheelNum = newWheelNum
 4         self.color = newColor
 5 
 6     def __str__(self):
 7         msg = "嘿。。。我的颜色是" + self.color + "我有" + int(self.wheelNum) + "个轮胎..."
 8         return msg
 9 
10     def move(self):
11         print('车在跑,目标:夏威夷')
12 
13 BMW = Car(4, "白色")
14 print(BMW)
15 #输出结果:嘿。。。我的颜色是白色,我有4个轮胎...
View Code
 1 class B:
 2     def __str__(self):
 3         return 'str : class B'
 4 
 5     def __repr__(self):
 6         return 'repr : class B'
 7 
 8 b = B()
 9 print('%s' % b)
10 print('%r' % b)
11 #执行结果为:
12 # str : class B
13 # repr : class B
View Code

__del__

创建对象后,python解释器默认调用__init__()方法;

当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

(在实例化一个对象的时候也会调用__del__方法)

 1 class Foo:
 2 
 3     def __del__(self):
 4         print('执行我啦')
 5 
 6 f1=Foo()
 7 del f1
 8 print('------->')
 9 
10 #输出结果
11 执行我啦
12 ------->
13 #在调用del时自动执行了类的内部__del__方法
View Code

__getitem__、__setitem__、__delitem__

 1 class Foo:
 2     def __init__(self,name):
 3         self.name=name
 4 
 5     def __getitem__(self, item):
 6         print(self.__dict__[item])
 7 
 8     def __setitem__(self, key, value):
 9         self.__dict__[key]=value
10     def __delitem__(self, key):
11         print('del obj[key]时,我执行')
12         self.__dict__.pop(key)
13     def __delattr__(self, item):
14         print('del obj.key时,我执行')
15         self.__dict__.pop(item)
16 
17 f1=Foo('sb')
18 f1['age']=18
19 f1['age1']=19
20 del f1.age1
21 del f1['age']
22 f1['name']='alex'
23 print(f1.__dict__)
24 
25 #执行结果为:
26 # del obj.key时,我执行
27 # del obj[key]时,我执行
28 # {'name': 'alex'}
View Code

__new__

__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

 1 class A(object):
 2     def __init__(self):
 3         print("这是 init 方法")
 4 
 5     def __new__(cls):
 6         print("这是 new 方法")
 7         return object.__new__(cls)
 8 
 9 A()
10 #输出结果为:
11 #这是init方法
12 #这是new方法
View Code
 1 class A:
 2     def __init__(self):
 3         self.x = 1
 4         print('in init function')
 5     def __new__(cls, *args, **kwargs):
 6         print('in new function')
 7         return object.__new__(A, *args, **kwargs)
 8 
 9 a = A()
10 #实例化时自动会调用__new__方法和__init__方法,先调用__new__方法
11 
12 #执行结果为:
13 # in new function
14 # in init function
View Code

__call__

对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

 1 class Foo:
 2     def __init__(self):
 3         pass
 4     
 5     def __call__(self, *args, **kwargs):
 6 
 7         print('__call__')
 8 
 9 obj = Foo() # 执行 __init__
10 obj()       # 执行 __call__
11 
12 #执行结果:__call__
View Code

__len__

 1 class A:
 2     def __init__(self):
 3         self.a = 1
 4         self.b = 2
 5         self.c = 1
 6 
 7     def __len__(self):
 8         return len(self.__dict__)   #返回内中属性的个数
 9 a = A()
10 print(len(a))
11 #执行结果为:3
12 #执行len方法会自动调用类中的__len__方法
View Code

__hash__

 1 class A:
 2     def __init__(self):
 3         self.a = 1
 4         self.b = 2
 5 
 6     def __hash__(self):
 7         return hash(str(self.a)+str(self.b))
 8 a = A()
 9 print(hash(a))
10 #类的外部执行hash()时会调用类中的__hash__方法
View Code

__eq__

 1 class A:
 2     def __init__(self):
 3         self.a = 1
 4         self.b = 2
 5 
 6     def __eq__(self,obj):
 7         if  self.a == obj.a and self.b == obj.b:
 8             return True
 9 a = A()
10 b = A()
11 print(a == b)
12 #True
View Code

文章中大部分实例都来自Eva_J老师的文章,原文见博客http://www.cnblogs.com/Eva-J/articles/7351812.html

猜你喜欢

转载自www.cnblogs.com/aberwang/p/9333947.html
今日推荐