最近,我在C#中做了很多工作(我的主要语言是Python),我喜欢做这样的事情
public string MyProperty{ get; set; }
回到Python,我忽略了这种功能。我不喜欢我不得不这么做
class MyClass:
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, value):
self._foo = value
a = MyClass()
a.foo = 7
print(a.foo)
我认为我可以很容易地用描述符来做这件事,就像这样。
class MyClass:
foo = AutoProperty()
a = MyClass()
a.foo = 7
print(a.foo)
不幸的是,我在实现这一点时意识到,我违反了我最喜欢的设计原则--吻。毕竟,我一直在想的只是实例变量。
class MyClass(): pass
a = MyClass()
a.foo = 7
print(a.foo)
我们在Python中不总是使用属性的原因是,通常情况下,获取和设置实例变量并不像Java这样的语言所涉及的那样多--这主要是因为private
、protected
和public
字段的概念在Python中并不真正存在,除了(弱的)约定和语言特性之外,而且因为从“字段”到“属性”在Python中并不是一个突破性的变化。
如果我们后来决定在设置或计算时确实需要更复杂的验证,那么我们可以通过实现属性而不影响类的接口来轻松地做到这一点。
但是,我仍然在想--这种技术,或者这种技术的一个改进版本,是否可以用来提供有用的Pythonic特性?
发布于 2015-07-30 09:53:30
在Python中,属性和属性之间的切换不是一种破坏性的更改,它根本不改变接口,因此自动属性系统没有多大意义。您可以从一个公共属性开始,然后在以后切换到一个属性,而不需要更改与类接口的代码。
这也是为什么不鼓励在Python中定义get_
和set_
方法;该属性是保护访问的一种更整洁的方法,并且意味着您不必从一开始就实现这些方法,以防以后需要它们做一些非琐碎的事情。参见例如您是否使用get/set模式(在Python中)? on SO。
如果您确实决定实现一个AutoProperty
,您也应该添加__delete__
;我使用以下内容作为其他描述符的基础:
class BaseDescriptor(object):
"""Descriptor base class, providing basic set, get and del methods.
Arguments:
name (str): The attribute to redirect access to (usually the name
to which the descriptor is assigned with a leading underscore,
indicating private-by-convention).
Example:
>>> class TestClass(object):
... foo = BaseDescriptor('_foo')
>>> inst = TestClass()
>>> inst.foo = 'bar'
>>> inst.foo
'bar'
>>> del inst.foo
>>> inst.foo
Traceback (most recent call last):
...
AttributeError: 'TestClass' object has no attribute '_foo'
"""
def __init__(self, name):
self.name = name
def __get__(self, obj, typ=None):
return getattr(obj, self.name)
def __set__(self, obj, val):
setattr(obj, self.name, val)
def __delete__(self, obj):
delattr(obj, self.name)
更新后的版本,供https://codereview.stackexchange.com/q/98892/32391审查
https://softwareengineering.stackexchange.com/questions/290878
复制相似问题