我这样做:

def set_property(property,value):  
def get_property(property):  

or

object.property = value  
value = object.property

python使用getter和setter的方法是什么?


当前回答

In [1]: class test(object):
    def __init__(self):
        self.pants = 'pants'
    @property
    def p(self):
        return self.pants
    @p.setter
    def p(self, value):
        self.pants = value * 2
   ....: 
In [2]: t = test()
In [3]: t.p
Out[3]: 'pants'
In [4]: t.p = 10
In [5]: t.p
Out[5]: 20

其他回答

In [1]: class test(object):
    def __init__(self):
        self.pants = 'pants'
    @property
    def p(self):
        return self.pants
    @p.setter
    def p(self, value):
        self.pants = value * 2
   ....: 
In [2]: t = test()
In [3]: t.p
Out[3]: 'pants'
In [4]: t.p = 10
In [5]: t.p
Out[5]: 20

这是一个老问题,但这个话题非常重要,而且一直是最新的。如果有人想超越简单的getter /setter,我已经写了一篇关于python中超级属性的文章,支持插槽,可观察性和简化的样板代码。

from objects import properties, self_properties


class Car:
    with properties(locals(), 'meta') as meta:

        @meta.prop(read_only=True)
        def brand(self) -> str:
            """Brand"""

        @meta.prop(read_only=True)
        def max_speed(self) -> float:
            """Maximum car speed"""

        @meta.prop(listener='_on_acceleration')
        def speed(self) -> float:
            """Speed of the car"""
            return 0  # Default stopped

        @meta.prop(listener='_on_off_listener')
        def on(self) -> bool:
            """Engine state"""
            return False

    def __init__(self, brand: str, max_speed: float = 200):
        self_properties(self, locals())

    def _on_off_listener(self, prop, old, on):
        if on:
            print(f"{self.brand} Turned on, Runnnnnn")
        else:
            self._speed = 0
            print(f"{self.brand} Turned off.")

    def _on_acceleration(self, prop, old, speed):
        if self.on:
            if speed > self.max_speed:
                print(f"{self.brand} {speed}km/h Bang! Engine exploded!")
                self.on = False
            else:
                print(f"{self.brand} New speed: {speed}km/h")
        else:
            print(f"{self.brand} Car is off, no speed change")

这个类可以这样使用:

mycar = Car('Ford')

# Car is turned off
for speed in range(0, 300, 50):
    mycar.speed = speed

# Car is turned on
mycar.on = True
for speed in range(0, 350, 50):
    mycar.speed = speed

这段代码将产生以下输出:

Ford Car is off, no speed change
Ford Car is off, no speed change
Ford Car is off, no speed change
Ford Car is off, no speed change
Ford Car is off, no speed change
Ford Car is off, no speed change
Ford Turned on, Runnnnnn
Ford New speed: 0km/h
Ford New speed: 50km/h
Ford New speed: 100km/h
Ford New speed: 150km/h
Ford New speed: 200km/h
Ford 250km/h Bang! Engine exploded!
Ford Turned off.
Ford Car is off, no speed change

更多关于如何和为什么的信息,请访问:https://mnesarco.github.io/blog/2020/07/23/python-metaprogramming-properties-on-steroids

试试这个:Python属性

示例代码如下:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        print("getter of x called")
        return self._x

    @x.setter
    def x(self, value):
        print("setter of x called")
        self._x = value

    @x.deleter
    def x(self):
        print("deleter of x called")
        del self._x


c = C()
c.x = 'foo'  # setter called
foo = c.x    # getter called
del c.x      # deleter called

您可以使用访问器/突变器(即@attr。Setter和@property)或不是,但最重要的是保持一致!

如果你只是使用@property来访问一个属性,例如:

class myClass:
    def __init__(a):
        self._a = a

    @property
    def a(self):
        return self._a

使用它来访问每个*属性!使用@property访问某些属性,而将其他一些属性保留为公共(即名称不带下划线)而没有访问器,这将是一个糟糕的做法,例如do not do

class myClass:
    def __init__(a, b):
        self.a = a
        self.b = b

    @property
    def a(self):
        return self.a

注意那个自我。B在这里没有显式访问器,尽管它是公共的。

与setter(或mutators)类似,可以随意使用@attribute。Setter,但要一致!当你做的时候。

class myClass:
    def __init__(a, b):
        self.a = a
        self.b = b 

    @a.setter
    def a(self, value):
        return self.a = value

It's hard for me to guess your intention. On one hand you're saying that both a and b are public (no leading underscore in their names) so I should theoretically be allowed to access/mutate (get/set) both. But then you specify an explicit mutator only for a, which tells me that maybe I should not be able to set b. Since you've provided an explicit mutator I am not sure if the lack of explicit accessor (@property) means I should not be able to access either of those variables or you were simply being frugal in using @property.

*例外情况是,当你显式地想要使某些变量可访问或可变,但不是两者,或者你想在访问或改变一个属性时执行一些额外的逻辑。这是我个人使用@property和@attribute的时候。Setter(否则没有显式的公共属性访问器/变异器)。

最后,PEP8和谷歌风格指南建议:

PEP8,为传承而设计说:

对于简单的公共数据属性,最好只公开属性名,而不需要复杂的访问器/突变器方法。请记住,如果您发现一个简单的数据属性需要增长函数行为,Python为将来的增强提供了一个简单的途径。在这种情况下,使用属性将函数实现隐藏在简单的数据属性访问语法后面。

另一方面,根据谷歌风格指南Python语言规则/属性,建议如下:

在新代码中使用属性来访问或设置数据,而通常使用简单、轻量级的访问器或setter方法。属性应该使用@property装饰器创建。

这种方法的优点:

通过消除用于简单属性访问的显式get和set方法调用,提高了可读性。允许延迟计算。考虑了维护类接口的python方式。就性能而言,当直接变量访问是合理的时,允许属性绕过了需要简单的访问器方法。这也允许将来在不破坏接口的情况下添加访问器方法。

优缺点:

必须从Python 2中的对象继承。可以隐藏像操作符重载这样的副作用。子类可能会让人困惑。

属性非常有用,因为你可以在赋值时使用它们,但也可以包括验证。你可以看到这段代码使用了装饰器@property和@<property_name>。Setter来创建方法:

# Python program displaying the use of @property 
class AgeSet:
    def __init__(self):
        self._age = 0

    # using property decorator a getter function
    @property
    def age(self):
        print("getter method called")
        return self._age

    # a setter function
    @age.setter
    def age(self, a):
        if(a < 18):
            raise ValueError("Sorry your age is below eligibility criteria")
        print("setter method called")
        self._age = a

pkj = AgeSet()

pkj.age = int(input("set the age using setter: "))

print(pkj.age)

在我写的这篇文章中也有更多的细节:https://pythonhowtoprogram.com/how-to-create-getter-setter-class-properties-in-python-3/