Реализация дескрипторов классов путем создания подкласса класса `type` - PullRequest
1 голос
/ 19 июля 2010

Я хотел бы иметь некоторые дескрипторы данных как часть класса.Это означает, что я хотел бы, чтобы атрибуты класса действительно были свойствами, доступ к которым осуществляется с помощью методов класса.

Кажется, что Python не поддерживает это напрямую, но его можно реализовать, создав подкласс typeучебный класс.Поэтому добавление свойства в подкласс type приведет к тому, что его экземпляры будут иметь дескрипторы для этого свойства.Его экземплярами являются классы.Таким образом, дескрипторы классов.

Желательно ли это?Есть ли какие-нибудь ошибки, за которыми мне следует следить?

Ответы [ 2 ]

1 голос
/ 19 июля 2010

Для дескриптора при обращении к классу принято (обычно) возвращать сам объект дескриптора.Это то, что делает property;если вы обращаетесь к объекту свойства в классе, вы возвращаете объект свойства (потому что это то, что выбирает метод __get__).Но это соглашение;вам не нужно делать это таким образом.

Итак, если вам нужен только дескриптор getter в вашем классе, и вы не возражаете против попытки установитьперезапишет дескриптор, вы можете сделать что-то вроде этого без программирования метакласса:

def classproperty_getter_only(f):
    class NonDataDescriptor(object):
        def __get__(self, instance, icls):
            return f(icls)
    return NonDataDescriptor()

class Foo(object):

    @classproperty_getter_only
    def flup(cls):
        return 'hello from', cls

print Foo.flup
print Foo().flup

для

('hello from', <class '__main__.Foo'>)
('hello from', <class '__main__.Foo'>)

Если вы хотите использовать полноценный дескриптор данных или хотите использовать встроенный-в объекте свойства, тогда вы правы, вы можете использовать метакласс и поместить его туда (понимая, что этот атрибут будет полностью невидим для экземпляров вашего класса; метаклассы не проверяются при выполнении поиска атрибутов в экземпляре класса).

Желательно ли?Я так не думаю.Я бы не стал делать то, что вы описываете случайно в рабочем коде;Я бы подумал об этом, только если бы у меня была очень веская причина для этого (и я не могу придумать такой сценарий из головы).Метаклассы очень мощные, но они не совсем понятны всем программистам, и их сложнее рассуждать, поэтому их использование усложняет поддержку вашего кода.Я думаю, что подобный дизайн был бы осужден сообществом питонов в целом.

1 голос
/ 19 июля 2010

Это то, что вы подразумеваете под "атрибутами класса, которые на самом деле являются свойствами, доступ к которым осуществляется методами класса"?

Вы можете использовать декоратор property, чтобы аксессор выглядел как фактический элемент данных. Затем вы можете использовать декоратор x.setter, чтобы создать установщик для этого атрибута.

Обязательно наследуйте от object, иначе это не сработает.

class Foo(object):
    def __init__(self):
            self._hiddenx = 3
    @property
    def x(self):
            return self._hiddenx + 10
    @x.setter
    def x(self, value):
            self._hiddenx = value

p = Foo()

p.x #13

p.x = 4
p.x #14
...