使用python属性,并且仍然能够明确地设置值
我想了解@property decorator是如何工作的 这里我使用方法y作为字段x的属性 在self.x属性具有属性之后,是否意味着无法显式设置该值 我认为,在变量上设置属性方法后,上一条语句-->c.x=2将不起作用使用python属性,并且仍然能够明确地设置值,python,Python,我想了解@property decorator是如何工作的 这里我使用方法y作为字段x的属性 在self.x属性具有属性之后,是否意味着无法显式设置该值 我认为,在变量上设置属性方法后,上一条语句-->c.x=2将不起作用 class C(object): def __init__(self): self.x = 0 self.list = [1,2,3,4,10] @property def y(self): print
class C(object):
def __init__(self):
self.x = 0
self.list = [1,2,3,4,10]
@property
def y(self):
print 'getting'
self.x = sum(self.list)
return self.x
@y.setter
def y(self, value):
print 'setting'
self.x = value
if __name__ == '__main__':
c = C()
print 'Value of c.y=',c.y
print '-'*80
c.y = 50
print '-'*80
print c.y
print '-'*80
if c.y >5:
print 'Hi'
您始终可以显式设置x
class Foo(object):
def __init__(self):
self.x = 1
self.lst = [1,2,3]
@property
def y(self):
self.x = sum(self.lst)
return self.x
@y.setter
def y(self,value):
self.x = value
f = Foo()
print f.y #6
print f.x #6
f.x = 3
print f.x #3
print f.y #6
print f.x #6
问题是,在本例中,调用getter(y
)也会设置x
属性的值,因此如果您通过y
进行所有更改,您将永远看不到x
的更改,因为查看y
的行为会更改x
的值
您可以尝试绕过该限制的一种方法是:
class Foo(object):
def __init__(self):
self.x = None
self.lst = [1,2,3]
@property
def y(self):
return sum(self.lst) if self.x is None else self.x
@y.setter
def y(self,value):
self.x = value
现在,如果您显式地为
x
(或y
)设置一个值,该值将一直保持,直到您将其设置回None
,如果您确实需要,您甚至可以在另一个用@y.deleter
修饰的函数中执行该操作。您始终可以显式地设置x
class Foo(object):
def __init__(self):
self.x = 1
self.lst = [1,2,3]
@property
def y(self):
self.x = sum(self.lst)
return self.x
@y.setter
def y(self,value):
self.x = value
f = Foo()
print f.y #6
print f.x #6
f.x = 3
print f.x #3
print f.y #6
print f.x #6
问题是,在本例中,调用getter(y
)也会设置x
属性的值,因此如果您通过y
进行所有更改,您将永远看不到x
的更改,因为查看y
的行为会更改x
的值
您可以尝试绕过该限制的一种方法是:
class Foo(object):
def __init__(self):
self.x = None
self.lst = [1,2,3]
@property
def y(self):
return sum(self.lst) if self.x is None else self.x
@y.setter
def y(self,value):
self.x = value
现在,如果您显式地为
x
(或y
)设置一个值,该值将一直保持,直到您将其设置回None
,如果您真的愿意,您甚至可以在另一个用@y.deleter
修饰的函数中执行该操作。通过名称篡改,对Python中的支持有限
为了避免暴露
x
,您需要两个前导下划线,即\uuux
在Python中,通过名称篡改对
为了避免暴露
x
,您需要两个前导下划线,即\uuux
您不能禁止使用属性装饰器直接更改属性,但我认为您可以这样做
class A(object):
def __init__(self):
self.x = 0
@property
def x(self):
return self.__dict__['x']
@x.setter
def x(self, value):
self.__dict__['x']=value
这将允许您实现您所描述的行为您不能禁止使用属性装饰器直接更改属性,但我认为您可以做到这一点
class A(object):
def __init__(self):
self.x = 0
@property
def x(self):
return self.__dict__['x']
@x.setter
def x(self, value):
self.__dict__['x']=value
这将允许您实现所描述的行为,如类Foo(对象):
def初始化(自身):
self.x=无
self.lst=[1,2,3]
@property
def y(self):
return sum(self.lst) if self.x is None else self.x
@y.setter
def y(self,value):
self.x = value
类Foo(对象):
def初始化(自身):
self.x=无
self.lst=[1,2,3]
@property
def y(self):
return sum(self.lst) if self.x is None else self.x
@y.setter
def y(self,value):
self.x = value
Python不提供任何阻止调用者访问变量的功能。换句话说,Python中没有“private”。按照惯例,带有下划线前缀的变量或方法不用于外部使用。例如:
class C(object):
def __init__(self):
self._x = 0
self.list = [1,2,3,4,10]
.
.
.
如果我真的愿意,我仍然可以访问\ux
,并且没有任何东西阻止我设置它
>>> c = C()
>>> c._x
10
>>> c._x = 20
>>> c._x
20
然而,按照惯例,下划线告诉我我正在做一些危险和不明智的事情。这取决于我,程序员,来决定我是否因为做了它而破坏了任何东西
这是在创建Python时做出的有意识的设计决策。这个想法是,任何使用你的类的人都要对他们使用它的行为负责;如果他们误用了它,它就坏了,那是他们的错。你用下划线警告他们。我认为一个聪明的程序员可以绕过你试图锁定它们的想法可能在这个决定中起了作用(比如反射库或直接与编译的字节码交互),但不要让我这么认为
稍微相关的是,如果变量(包括其他导入的模块、函数等)是模块的成员,下划线实际上会起作用。import*
不会导入以下划线开头的成员。例如:
a、 派克
命令提示:
>>> from a import *
>>> b
50
>>> _a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_a' is not defined
来自导入的>>*
>>>b
50
>>>_a
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
名称错误:未定义名称“\u a”
在您的特定示例中,
x及其setter相对无用,因为您在调用getter时会重写其值。Python不提供任何阻止调用方访问变量的功能。换句话说,Python中没有“private”。按照惯例,带有下划线前缀的变量或方法不用于外部使用。例如:
class C(object):
def __init__(self):
self._x = 0
self.list = [1,2,3,4,10]
.
.
.
如果我真的愿意,我仍然可以访问\ux
,并且没有任何东西阻止我设置它
>>> c = C()
>>> c._x
10
>>> c._x = 20
>>> c._x
20
然而,按照惯例,下划线告诉我我正在做一些危险和不明智的事情。这取决于我,程序员,来决定我是否因为做了它而破坏了任何东西
这是在创建Python时做出的有意识的设计决策。这个想法是,任何使用你的类的人都要对他们使用它的行为负责;如果他们误用了它,它就坏了,那是他们的错。你用下划线警告他们。我认为一个聪明的程序员可以绕过你试图锁定它们的想法可能在这个决定中起了作用(比如反射库或直接与编译的字节码交互),但不要让我这么认为
稍微相关的是,如果变量(包括其他导入的模块、函数等)是模块的成员,下划线实际上会起作用。import*
不会导入以下划线开头的成员。例如:
a、 派克
命令提示:
>>> from a import *
>>> b
50
>>> _a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_a' is not defined
来自导入的>>*
>>>b
50
>>>_a
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
名称错误:未定义名称“\u a”
在您的特定示例中,x
及其setter相对无用,因为您在调用getter时会重写其值。对不起,您指的是哪一行?我看不到c.x=2