Реализация дескрипторов классов путем создания подкласса класса `type`

StackOverflow https://stackoverflow.com/questions/3277047

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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'>)

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

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

Другие советы

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

Вы можете использовать декоратор 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top