在面向对象编程中,把方法(函数)看作对象的接口。直接访问对象的属性可能是不安全的,或设计上不够灵活。但是使用调用方法在形式上不如访问属性简洁
circle.getRadius()
circle.setRadius(5.0) # 繁
circle.radius
circle.radius = 5.0 # 简
能否在形式上是属性访问,但实际上调用方法?
from math import pi
class Circle(object):
def __init__(self, radius):
self.radius = radius
def getRadius(self):
# 灵活性 return round(self.radius, 2)
return self.radius
def setRadius(self, value):
if not isinstance(value, (int, long, float)):
raise ValueError('wrong type.')
self.radius = float(value)
def getArea(self):
return self.radius ** 2 * pi
c = Circle(3.2)
c.radius = 'abc'
d = c.radius * 2
print d # 运行没错,逻辑错误;
# 安全方面
c.setRadius('abc')
# 灵活性,无法对输入再做操作,因为直接访问到了内部属性
c.getRadius()
但访问器和设置器使用繁琐:使用property函数为类创建可管理属性,fget/fset/fdel对应相应属性访问
from math import pi
class Circle(object):
def __init__(self, radius):
self.radius = radius
def getRadius(self):
return self.radius
def setRadius(self, value):
if not isinstance(value, (int, long, float)):
raise ValueError('wrong type.')
self.radius = float(value)
def getArea(self):
return self.radius ** 2 * pi
R = property(getRadius, setRadius)
c = Circle(3.2)
print c.R
c.R = '3'
print c.R
c.R = 'abc'
类比较
自定义的类,实例间可以使用<,<=,>,>=,==,!=符号进行比较,自定义比较的行为。
例如,有一个矩形的类,希望比较两个矩形的实例时,比较的是他们的面积
class Rectangle:
def __init__(self,w,h):
self.w = w
self.h = h
def area(self):
return self.w*self.h
rect1 = Rectangle(5,3)
rect2 = Rectangle(4,4)
rect1 > rect2 # => rect1.area() > rect2.area()
# 运算符重载,需实现如下方法:
__lt__,__le__,__gt__,__ge__,__eq__,__ne__
< <= > >= = !=
使用标准库下的functools下的类装饰器total_ordering可以简化此过程
class Rectangle:
def __init__(self,w,h):
self.w = w
self.h = h
def area(self):
return self.w*self.h
def __lt__(self,obj):
return self.area() < obj.area()
def __le__(self,obj):
return self.area() <= obj.area()
r1 = Rectangle(5,3)
r2 = Rectangle(4,4)
r1 < r2 # 实际调用 r1.__lt__(r2)
r1 <= r2
from functools import total_ordering
@total_ordering
class Rectangle:
def __init__(self,w,h):
self.w = w
self.h = h
def area(self):
return self.w*self.h
def __eq__(self,obj): # 重载两个方法,其中一个为等于,另一个随意
return self.area() == obj.area()
def __lt__(self,obj):
return self.area() < obj.area()
rect1 = Rectangle(5,3)
rect2 = Rectangle(4,4)
r1 <= r2
多个修饰器
def outter61(func1):
def inner61(*args,**kwargs):
print("第一个装饰器~~~~111")
func1(*args,**kwargs)
return inner61
def outter62(func2):
def inner62(*args,**kwargs):
print("第二个装饰器~~~~2222")
func2(*args,**kwargs)
return inner62
def outter63(func3):
def inner63(*args,**kwargs):
func3(*args, **kwargs)
print("第三个装饰器~~~~333")
return inner63
@outter61
@outter62
@outter63
def check():
print("check")
check()
"""
输出结果:
第一个装饰器~~~~111
第二个装饰器~~~~2222
check
第三个装饰器~~~~333
"""
仅由程序执行过程来看,先执行outter61. 进入outter61后,
首先打印("第一个装饰器~~~~111")
下一步执行func1,此时func1的执行需要调用inner62才能完成,
执行过程进入inner62后打印("第二个装饰器~~~~2222")
下一步执行func2,此时func2的执行需要调用inner63,
执行过程进入inner63,此时func3正是被传入(装饰)的原函数check(),
继而返回inner63,执行inner63内剩余步骤,即打印("第三个装饰器~~~~333")
执行过程进入原函数,打印check(输出到此结束,但是程序的执行还未停止),
执行到这一步,返回到inner62,func2对inner63的调用完成。
执行到这一步,返回到inner61,func1对inner62的调用完成。
整个函数结束。
6.3【类与对象】可管理的对象属性及类比较
最新推荐文章于 2024-11-04 22:26:34 发布
文章讨论了在面向对象编程中,如何通过方法作为对象的接口来提高安全性与灵活性,对比了直接访问属性和使用方法的优缺点。介绍了使用`property`来创建访问器和设置器,以及如何通过重载运算符实现对象间的比较。此外,还展示了装饰器的概念及其在多层调用中的工作原理。
摘要由CSDN通过智能技术生成