В моих усилиях в качестве ученика-питона я недавно застрял в каком-то странном (с моей точки зрения) поведении, если попытался работать с атрибутами класса.Я не жалуюсь, но был бы признателен за некоторые полезные комментарии, чтобы пролить свет на этот вопрос.
Чтобы свести сложный вопрос к более краткому вопросу, я бы сформулировал его так:
Чтоявляется "питоническим" способом гарантировать, что атрибут класса ведет себя больше как статическая переменная в дереве наследования?
Мне кажется, что атрибут класса ведет себя как значение по умолчанию "копировать при чтении" сполиморфные характеристики.Пока я выполняю операции «только для чтения», он остается «синглтоном», но как только я получаю доступ к атрибуту класса с помощью присваивания через производный класс или экземпляр, он превращается в новую ссылку, теряя отношение кунаследованная базовая ссылка.
(У этого есть определенный потенциал для некоторых интересных функций, но вы должны понять это, чтобы охватить его, поэтому некоторая проницательность высоко ценится.)
class A(object):
classvar = 'A'
def setclassvar(self, value):
A.classvar = value
def __str__(self):
return "%s id(%s) " %(A.classvar, hex(id(A.classvar))[2:-1].upper())
class A1(A):
pass
class B(object):
classvar = 'B'
def setclassvar(self, value):
self.__class__.classvar = value
def __str__(self):
cvar = self.__class__.classvar
return "%s id(%s) " %(cvar, hex(id(cvar))[2:-1].upper())
class B1(B):
def setclassvar(self, value):
self.__class__.classvar = value
a, a1 = A(), A1()
a1.setclassvar('a')
print "new instance A: %s" %a
print "new instance A1: %s" %a
b, b1 = B(), B1()
b1.setclassvar('bb')
print "new instance B: %s" %b
print "new instance B1: %s" %b1
a1.setclassvar('aa')
print "new value a1: %s" %a
print "new value a: %s" %a
a1.classvar = 'aaa'
print "direct access a1: %s id(%s)" %(a1.classvar, hex(id(a1.classvar))[2:-1].upper())
print "method access a1: %s" %a1
print "direct access a: %s" %a
производитследующее:
new instance A: a id(B73468A0)
new instance A1: a id(B73468A0)
new instance B: B id(B73551C0)
new instance B1: bb id(AD1BFC)
new value a1: aa id(AD1BE6)
new value a: aa id(AD1BE6)
direct access a1: aaa id(A3A494)
method access a1: aa id(AD1BE6)
direct access a: aa id(AD1BE6)
Таким образом, прямой (назначающий) доступ object.classvar
или опосредованный через self.__class__.classvar
не совпадают с BASECLASS.classvar
.
Isэто вопрос сферы или что-то совсем другое.
Ждем ваших ответов и спасибо вперед.: -)
Редактировать: В течение очень короткого времени был дан ответ, предлагающий использовать дескрипторы классов, такие как: Как создать свойство класса? .
К сожалению, это не работает:
class Hotel(Bar):
def __init__(self):
Hotel.bar += 1
hotel = Hotel()
assert hotel.bar == 51
assert hotel.bar == foo.bar
2-е утверждение не выполняется!hotel.bar не ссылается на тот же объект, что и foo.bar
, а hotel.bar
ссылается на что-то другое, чем Hotel.bar!
2-е редактирование: я прекрасно знаю, что синглтоны считаются "антипаттернами""и я не собирался их использовать (экстенсивно).Поэтому я не упомянул их в вопроснике.Несмотря на то, что существует множество решений, обсуждающих и предлагающих решения с и о синглетонах, мой вопрос остается: почему переменная класса может так легко отсоединить свою ссылку?Ruby ведет себя более естественно для меня: http://snippets.dzone.com/posts/show/6649