Python特性

1.特性定义

通过存取方法定义的属性通常称为特性。在Python中,可以使用函数——property来创建特性。

2.函数property

它使用起来很简单。

class Rectangle:
    def __init__(self):
        self.width=0
        self.height=0
    def set_size(self,size):
        self.width,self.height=size
    def get_size(self):
        return self.width,self.height
    size=property(get_size,set_size)

调用函数property并将存取方法作为参数(获取方法在前,设置方法在后)。创建了一个特性,然后将名称size关联到这个特性。这样就可以以同样的方式对待width,height和size

r=Rectangle()
r.width=10
r.height=10
print(r.size)
r.size=200,100
print(r.width)
#运行结果
(10, 10)
200

如你所见,属性size仍然受制于get_size和set_size执行的计算,但看起来就像普通属性一样。
事实上,调用函数property时也可以不指定参数,或者指定一个、三个、四个参数。如果没有指定任何参数,创建的特性即不可读又不可写。如果只指定了一个参数(获取方法),创建的特性将是只读的。第三个参数是可选的,指定用于删除属性的方法(这个方法不接受任何参数)。第四个参数也是可选的,指定一个文档字符串,可使用它吗作为关键字参数来实现。

3.静态方法和类方法

两种方法的创建:将它们分别包装在staticmethod和classmethod类的对象中。静态方法的定义中没有参数self,可直接通过类来调用。类方法的定义中包含类似于self的参数,通常被命名为cls。对于类方法也可通过对象直接调用,但参数cls将自动关联到类。

class MyClass:
    def smeth(self):
        print('静态方法')
smeth = staticmethod(smeth)   
def cmeth(cls):
    print('类方法')
cmeth=classmethod(cmeth)

像这样手工包装和替换方法很繁琐。可以使用一种名为装饰器的新语法.
它可以用于像这样的包装方法。(实际上,装饰器可用于包装任何可调用的对象,并且可用于方法和函数。)指定一个或多个装饰器,可以在方法(或函数)前面使用运算符@列出这些装饰器。当指定多个装饰器时,应用的顺序和列出的顺序相反。

class MyClass:
    @staticmethod
    def smeth():
        print('静态方法')
    @classmethod
    def cmeth(cls):
        print('类方法',cls)
MyClass.smeth()
MyClass.cmeth()
#运行结果
静态方法
类方法 <class '__main__.MyClass'>

在Python中,静态方法和类方法一直都不太重要,主要是因为总是可以使用函数或关联的方法替代它们。但是在如工厂函数这些方面还是有用武之地的。

4. _ getattr_、_ setattr_等方法

可以拦截对象属性的所用访问企图。要在属性被访问时执行一段代码,必须使用一些魔法方法。下面的四个魔法方法提供了你需要的所有功能:
口__getattribute___(self,name):在属性被访问时自动调用(只适用于新式类)。
口__getattr___(self,name):在属性被访问而对象没有这样的属性时自动调用。
口___setattr__(self, name, value):试图给属性赋值时自动调用。
口___delattr___(self,name):试图删除属性时自动调用。
相比函数property,这些魔法方法使用起来要棘手些(效率也更低),但它们很有用,因为你可以在这些方法中编写处理多个特性的代码。

class Rectangle:
    def __init__(self):
        self.width=0
        self.height=0
    def __setattr__(self, name, value):
        if name=='size':
            self.width,self.height=value
        else:
            self.__dict__[name]=value
    def __getattr__(self,name):
        if name=='size':
            return self.width,self.height
        else:
            raise AttributeError()

需要注意如下两点:
□即便涉及的属性不是size,也将调用方法_setattr__。因此这个方法必须考虑如下两种情形:如果涉及的属性为size,就执行与以前一样的操作;否则就使用魔法属性dict.__ dict__属性是一个字典,其中包含所有的实例属性。之所以使用它而不是执行常规属性赋值,是因为旨在避免再次调用__ setattr__ ,进而导致无限循环。
口仅当没有找到指定的属性时,才会调用方法_getattr__。这意味着如果指定的名称不是size,这个方法将引发AttributeError异常。这在要让类能够正确地支持hasattr和getattr等内置函数时很重要。如果指定的名称为size,就使用前一个实现中的表达式。


编写方法_setattr_时需要避开无限循环陷阱,编写_getattribute_同样如此。由于它拦截对所有属性的访问,因此将拦截对_dict__的访问!在_getattribute_中访问当前实例的属性时,唯一安全的方式是使用超类的方法__getattribute_ (使用super)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值