我这样做:

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

or

object.property = value  
value = object.property

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


当前回答

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

“Pythonic”的方法不是使用“getter”和“setter”,而是使用简单的属性,就像问题所演示的那样,以及del用于删除(但是为了保护无辜的人,更改了名称……内置命令):

value = 'something'

obj.attribute = value  
value = obj.attribute
del obj.attribute

如果稍后,你想修改设置和获取,你可以这样做,而不必修改用户代码,通过使用属性装饰器:

class Obj:
    """property demo"""
    #
    @property            # first decorate the getter method
    def attribute(self): # This getter method name is *the* name
        return self._attribute
    #
    @attribute.setter    # the property decorates with `.setter` now
    def attribute(self, value):   # name, e.g. "attribute", is the same
        self._attribute = value   # the "value" name isn't special
    #
    @attribute.deleter     # decorate with `.deleter`
    def attribute(self):   # again, the method name is the same
        del self._attribute

(每次使用装饰器都会复制并更新前面的属性对象,因此请注意,您应该为每个set、get和delete函数/方法使用相同的名称。)

在定义了上面的代码之后,原来的设置、获取和删除代码是一样的:

obj = Obj()
obj.attribute = value  
the_value = obj.attribute
del obj.attribute

你应该避免这样做:

def set_property(属性,值): def get_property(财产):

首先,上面的方法不起作用,因为你没有为属性将要设置为的实例提供参数(通常是self),即:

class Obj:

    def set_property(self, property, value): # don't do this
        ...
    def get_property(self, property):        # don't do this either
        ...

其次,这重复了两个特殊方法__setattr__和__getattr__的目的。

第三,我们还有setattr和getattr内置函数。

setattr(object, 'property_name', value)
getattr(object, 'property_name', default_value)  # default is optional

@property装饰器用于创建getter和setter。

例如,我们可以修改设置行为来限制正在设置的值:

class Protective(object):

    @property
    def protected_value(self):
        return self._protected_value

    @protected_value.setter
    def protected_value(self, value):
        if acceptable(value): # e.g. type or range check
            self._protected_value = value

一般来说,我们希望避免使用属性,而只是使用直接属性。

这是Python用户所期望的。遵循最小惊喜原则,你应该尽量满足用户的期望,除非你有非常令人信服的相反理由。

示范

例如,我们需要我们的对象的protected属性是一个0到100之间的整数,并防止它的删除,用适当的消息告知用户它的正确用法:

class Protective(object):
    """protected property demo"""
    #
    def __init__(self, start_protected_value=0):
        self.protected_value = start_protected_value
    # 
    @property
    def protected_value(self):
        return self._protected_value
    #
    @protected_value.setter
    def protected_value(self, value):
        if value != int(value):
            raise TypeError("protected_value must be an integer")
        if 0 <= value <= 100:
            self._protected_value = int(value)
        else:
            raise ValueError("protected_value must be " +
                             "between 0 and 100 inclusive")
    #
    @protected_value.deleter
    def protected_value(self):
        raise AttributeError("do not delete, protected_value can be set to 0")

(注意,__init__指的是self。但属性方法引用self._protected_value。这样,__init__就可以通过公共API使用该属性,确保它是“受保护的”。)

和用法:

>>> p1 = Protective(3)
>>> p1.protected_value
3
>>> p1 = Protective(5.0)
>>> p1.protected_value
5
>>> p2 = Protective(-5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> p1.protected_value = 7.3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 17, in protected_value
TypeError: protected_value must be an integer
>>> p1.protected_value = 101
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> del p1.protected_value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 18, in protected_value
AttributeError: do not delete, protected_value can be set to 0

名字重要吗?

是的。setter和。deleter会复制原始属性。这允许子类在不改变父类中的行为的情况下正确地修改行为。

class Obj:
    """property demo"""
    #
    @property
    def get_only(self):
        return self._attribute
    #
    @get_only.setter
    def get_or_set(self, value):
        self._attribute = value
    #
    @get_or_set.deleter
    def get_set_or_delete(self):
        del self._attribute

现在为了让它工作,你必须使用各自的名称:

obj = Obj()
# obj.get_only = 'value' # would error
obj.get_or_set = 'value'  
obj.get_set_or_delete = 'new value'
the_value = obj.get_only
del obj.get_set_or_delete
# del obj.get_or_set # would error

我不确定这在什么情况下有用,但用例是如果您想要一个get、set和/或delete-only属性。可能最好是使用语义上相同的属性和相同的名称。

结论

从简单的属性开始。

如果以后需要设置、获取和删除相关的功能,可以使用属性装饰器添加它。

避免使用名为set_…和get_……-这就是属性的作用。

其他回答

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

“Pythonic”的方法不是使用“getter”和“setter”,而是使用简单的属性,就像问题所演示的那样,以及del用于删除(但是为了保护无辜的人,更改了名称……内置命令):

value = 'something'

obj.attribute = value  
value = obj.attribute
del obj.attribute

如果稍后,你想修改设置和获取,你可以这样做,而不必修改用户代码,通过使用属性装饰器:

class Obj:
    """property demo"""
    #
    @property            # first decorate the getter method
    def attribute(self): # This getter method name is *the* name
        return self._attribute
    #
    @attribute.setter    # the property decorates with `.setter` now
    def attribute(self, value):   # name, e.g. "attribute", is the same
        self._attribute = value   # the "value" name isn't special
    #
    @attribute.deleter     # decorate with `.deleter`
    def attribute(self):   # again, the method name is the same
        del self._attribute

(每次使用装饰器都会复制并更新前面的属性对象,因此请注意,您应该为每个set、get和delete函数/方法使用相同的名称。)

在定义了上面的代码之后,原来的设置、获取和删除代码是一样的:

obj = Obj()
obj.attribute = value  
the_value = obj.attribute
del obj.attribute

你应该避免这样做:

def set_property(属性,值): def get_property(财产):

首先,上面的方法不起作用,因为你没有为属性将要设置为的实例提供参数(通常是self),即:

class Obj:

    def set_property(self, property, value): # don't do this
        ...
    def get_property(self, property):        # don't do this either
        ...

其次,这重复了两个特殊方法__setattr__和__getattr__的目的。

第三,我们还有setattr和getattr内置函数。

setattr(object, 'property_name', value)
getattr(object, 'property_name', default_value)  # default is optional

@property装饰器用于创建getter和setter。

例如,我们可以修改设置行为来限制正在设置的值:

class Protective(object):

    @property
    def protected_value(self):
        return self._protected_value

    @protected_value.setter
    def protected_value(self, value):
        if acceptable(value): # e.g. type or range check
            self._protected_value = value

一般来说,我们希望避免使用属性,而只是使用直接属性。

这是Python用户所期望的。遵循最小惊喜原则,你应该尽量满足用户的期望,除非你有非常令人信服的相反理由。

示范

例如,我们需要我们的对象的protected属性是一个0到100之间的整数,并防止它的删除,用适当的消息告知用户它的正确用法:

class Protective(object):
    """protected property demo"""
    #
    def __init__(self, start_protected_value=0):
        self.protected_value = start_protected_value
    # 
    @property
    def protected_value(self):
        return self._protected_value
    #
    @protected_value.setter
    def protected_value(self, value):
        if value != int(value):
            raise TypeError("protected_value must be an integer")
        if 0 <= value <= 100:
            self._protected_value = int(value)
        else:
            raise ValueError("protected_value must be " +
                             "between 0 and 100 inclusive")
    #
    @protected_value.deleter
    def protected_value(self):
        raise AttributeError("do not delete, protected_value can be set to 0")

(注意,__init__指的是self。但属性方法引用self._protected_value。这样,__init__就可以通过公共API使用该属性,确保它是“受保护的”。)

和用法:

>>> p1 = Protective(3)
>>> p1.protected_value
3
>>> p1 = Protective(5.0)
>>> p1.protected_value
5
>>> p2 = Protective(-5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> p1.protected_value = 7.3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 17, in protected_value
TypeError: protected_value must be an integer
>>> p1.protected_value = 101
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> del p1.protected_value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 18, in protected_value
AttributeError: do not delete, protected_value can be set to 0

名字重要吗?

是的。setter和。deleter会复制原始属性。这允许子类在不改变父类中的行为的情况下正确地修改行为。

class Obj:
    """property demo"""
    #
    @property
    def get_only(self):
        return self._attribute
    #
    @get_only.setter
    def get_or_set(self, value):
        self._attribute = value
    #
    @get_or_set.deleter
    def get_set_or_delete(self):
        del self._attribute

现在为了让它工作,你必须使用各自的名称:

obj = Obj()
# obj.get_only = 'value' # would error
obj.get_or_set = 'value'  
obj.get_set_or_delete = 'new value'
the_value = obj.get_only
del obj.get_set_or_delete
# del obj.get_or_set # would error

我不确定这在什么情况下有用,但用例是如果您想要一个get、set和/或delete-only属性。可能最好是使用语义上相同的属性和相同的名称。

结论

从简单的属性开始。

如果以后需要设置、获取和删除相关的功能,可以使用属性装饰器添加它。

避免使用名为set_…和get_……-这就是属性的作用。

您可以使用访问器/突变器(即@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中的对象继承。可以隐藏像操作符重载这样的副作用。子类可能会让人困惑。

你可以使用神奇的方法__getattribute__和__setattr__。

class MyClass:
    def __init__(self, attrvalue):
        self.myattr = attrvalue
    def __getattribute__(self, attr):
        if attr == "myattr":
            #Getter for myattr
    def __setattr__(self, attr):
        if attr == "myattr":
            #Setter for myattr

注意__getattr__和__getattribute__是不同的。__getattr__只在未找到属性时调用。

使用@property和@attribute。Setter不仅可以帮助您使用“pythonic”方式,还可以在创建对象和更改对象时检查属性的有效性。

class Person(object):
    def __init__(self, p_name=None):
        self.name = p_name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, new_name):
        if type(new_name) == str: #type checking for name property
            self._name = new_name
        else:
            raise Exception("Invalid value for name")

通过这种方式,您实际上可以向客户端开发人员“隐藏”_name属性,并对name属性类型进行检查。请注意,即使在初始化过程中也会调用setter。所以:

p = Person(12)

会导致:

Exception: Invalid value for name

But:

>>>p = person('Mike')
>>>print(p.name)
Mike
>>>p.name = 'George'
>>>print(p.name)
George
>>>p.name = 2.3 # Causes an exception

试试这个: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