python中面向对象:@property

前言

最近在看一些源代码时,发现很多工程会用到python面向对象的一些高级一点的属性(至少是我之前没用过的,感觉自己的代码还是太低级了。所以在这里记录一下:

参考

@property

我阅读的代码如下所示:

    @property
    def ofmap_size(self):
        """
        Get size of one output fmap.
        """
        return self.hofm * self.wofm * self.nimg

    @property
    def total_ofmap_size(self):
        """
        Get total size of all output fmaps.
        """
        return self.nofm * self.ofmap_size

这是一个实现深度学习模型算子融合的代码,其中这是为表示模型层新构建的类,这两个方法主要是返回该层输出激活尺寸和所有的输出激活大小。再看代码时我在想如果我写,我肯定不会加入@property属性,不知道其有什么作用。

第一个参考资料:

在第一个参考资料中,其说明如果在一个类中的方法加入@property属性修饰,那么该方法就可以用像调用类属性的格式调用,例如下面的示例:

class Dog:
    def __init__(self, name, gender, age, type) -> None:
        self.name = name
        self.gender = gender
        self.age = age
        self.type = type

    @property
    def grow(self):
        age = self.age + 1
        return age

dog = Dog("xiaohei", "male", 5, "tugou")
new_age = dog.grow
print(dog.age, new_age)

结果:

5  6

如果我们以另一种方式调用grow,如:new_age = dog.grow(),那么会报错如下:

----> 1 new_age = dog.grow()
      2 print(dog.age, new_age)

TypeError: 'int' object is not callable

也就是说,在这里,本来是作为方法的grow,现在变成了一个属性。

用法

在资料中,其指出,该方法可以被用作返回python中的只读属性,在python中没有真正实现只读属性,借用评论区中的评论:

类中定义私有属性有两种方式:一种用单下划线,表示这个属性是类的私有属性,不希望被外部访问到,但仅仅是不希望,还是可以被访问的;第二种是双下划线,表示这个属性就是类的私有属性,只能在类中被使用,不可以在实例化的对象中去使用。

纠正一下,类中 单下划线和双下划线的属性,在类外部,均可以使用实例化对象访问并且修改。区别在于:双下划线的属性名 ____FileName 被解释器重写为 _ClassName__FileName ,所以访问或者修改它的时候是 实例名._ClassName__FileName ,而单下划线的属性 _FileName,依然可以用 实例名._FileName 访问或修改

那么我们就可以使用上述@property实现一种只读属性方法,如下:

class Dog:
    def __init__(self, name, gender, age, type) -> None:
        self.name = name
        self.gender = gender
        self._age = age
        self.type = type

    @property
    def age(self):
        return self._age

dog = Dog("xiaohei", "male", 5, "tugou")
print(dog.age)

结果:

5
dog.age += 1
print(dog.age)

结果:

AttributeError                            Traceback (most recent call last)
 in 
----> 1 dog.age += 1
      2 print(dog.age)

AttributeError: can't set attribute

这样的话,用户可以直接用dog.age返回其age属性,但是又不能随意修改。这样就很像实现了只读属性。

第二个参考资料

上面我们只实现了只读属性,我们不能直接修改它,除非直接调用_age属性。而我们可以使用另一种方法实现对其修改。代码如下:

class Dog:
    def __init__(self, name, gender, age, type) -> None:
        self.name = name
        self.gender = gender
        self._age = age
        self.type = type

    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self, new):
        self._age = new

dog = Dog("xiaohei", "male", 5, "tugou")
print(dog.age)
dog.age = 8
print(dog.age)

结果:

5
8

可以看到,类中表示age的真实属性是_age,但是我们通过dog.age就实现了对其访问和修改,就很像我们在C++中设置私有属性_age,而设置公有方法get_ageset_age对该私有属性进行操作。

猜你喜欢

转载自blog.csdn.net/qq_43219379/article/details/130163929