Найти - Пользователи
Полная версия: property и super
Начало » Python для экспертов » property и super
1
f1aky
имеем два класса
class A(object):

@property
def x(self):
return 1


class B(A):

@property
def x(self):
return super(B, self).x * 2


>>>b= B()
>>>b.x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in t
TypeError: must be type, not classobj

как быть??

P.S. знаю что можно так
class B(A):

@propety
def x(self):
return A.x.fget(self) * 2
но мне надо через super.
f1aky
погуглил понял, что через super никак, это баг и он не исправлен.
нашел два обходных пути, может кому пригодиться:
1.
class A_(object):

def _get_x(self):
return 1

x = property(fget= _get_x)


class B_(A_):

def _get_x(self):
return super(B_, self)._get_x(self) * 2

x = property(fget= _get_x)
2.
class PropertyMeta(type):

def __new__(cls, name, bases, dct):
property_dict = dict()
for k,v in dct.items():
if isinstance(v, property):
property_dict[k] = v
for base in bases:
for k, v in base.__dict__.items():
if property_dict.get(k) and isinstance(v, property):
if v.fget:
dct['_get_%s' % k] = v.fget
if v.fset:
dct['_set_%s' % k] = v.set
if v.fdel:
dct['_del_%s' % k] = v.fdel
return type.__new__(cls, name, bases, dct)

class A(object):

@property
def x(self):
return 1


class B(A):
__metaclass__ = PropertyMeta

@property
def x(self):
return self._get_x() * 2
Первый метод как по мне лудче юзать когда пару проперти атрибутов, намного нагляднее будет. Второй конда много проперти атрибутов, магия, но меньше гемороя и лишнего кода.
f1aky
переписал метакласс, теперь если ptoperty метод(getter, setter, deleter) в ребенке не определен, берет его от предка.
class PropertyMeta(type):
def __new__(cls, name, bases, dct):
property_dict = dict()
for k,v in dct.items():
if isinstance(v, property):
property_dict[k] = v
for base in bases:
for k, v in base.__dict__.items():
if property_dict.get(k) and isinstance(v, property):
p = property_dict.get(k)
for f_type in ['fget', 'fset', 'fdel']:
if getattr(v, f_type):
dct['_%s_%s' % (f_type[1:], k)] = getattr(v, f_type)
if not getattr(p, f_type):
dct[k] = cls._set_property_func(dct[k], f_type, getattr(v, f_type))

return type.__new__(cls, name, bases, dct)

@classmethod
def _set_property_func(cls, obj, key, func):
# через setattr вылитает ошибка, что обьекты из dct только для чтения
fget = obj.fget
fset = obj.fset
fdel = obj.fdel
if key == 'fget': fget = func
elif key == 'fset': fset = func
else: fdel == func
return property(fget= fget, fset= fset, fdel= fdel)
пример использования
class A(object):
@property
def x(self):
return 1

@x.setter
def x(self, value):
print 'set x = %s' % value

class B(A):
__metaclass__ = PropertyMeta
@property
def x(self):
return self._get_x() * 2


@x.deleter
def x(self):
print 'del x'

>>> b=B()
>>> b.x
2
>>> b.x=10
set x = 10
>>> del b.x
del x
Замечания по коду приветствуються
JOHN_16
f1aky
>>>b= b()
после этого не читал, не люблю когда показывают не тот код что нужно. Пожалуйста, оформляйте пост корректно.
f1aky
вам показывать сотни строк кода? вы их будите смотреть?? я не уверен.
про отпечатку извените, исправил.
FishHook
f1aky
вам показывать сотни строк кода? вы их будите смотреть?? я не уверен.про отпечатку извените, исправил.

>>>b.x
>>> b.t

что такое b.t мы должны догадаться?
f1aky
сорь, писал ночью, вот и опечатки такие
FishHook
f1aky
сорь, писал ночью, вот и опечатки такие
Вот теперь вконец запутал!
Код из стартового поста выполняется без ошибок
f1aky
ээ действительно работает походу весь бок вышел в том, что когда я в консоле набирал забыл от А насдедовать от object
прошу закрыть этот фейл. Извеняюсь
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB