Свойства Python и Большой глоток

Работа Эффективно с Унаследованным кодом является действительно удивительной книгой, которая вдается в большие подробности о том, как к правильно модульному тесту Ваш код и каково истинное преимущество его. Это действительно открыло мои глаза.

18
задан fuzzy-waffle 26 July 2009 в 04:17
поделиться

3 ответа

Ох, это сложно (и весело). SWIG не рассматривает это как возможность сгенерировать @property: я думаю, было бы слишком легко ошибиться и распознать множество ложных срабатываний, если бы это не было сделано очень осторожно. Однако, поскольку SWIG не будет делать этого при генерации C ++, все еще вполне возможно сделать это в Python, используя небольшой метакласс.

Итак, ниже, допустим, у нас есть класс Math, который позволяет нам устанавливать и получать целочисленную переменную названный «пи».

4
ответ дан 30 November 2019 в 05:54
поделиться

У меня была та же проблема, и совет использовать% pythoncode мне помог. Вот что я сделал:

class Foo {
  // ...
  std::string get_name();
  bool set_name(const std::string & name);
};

В оболочке:

%include "foo.h"
%pythoncode %{
def RaiseExceptionOnFailure(mutator):
  def mutator(self, v):
    if not mutator(self, v):
     raise ValueError("cannot set property")
  return wrapper
Foo.name = property(Foo.get_name, RaiseExceptionOnFailure(Foo.set_name))
%}
1
ответ дан 30 November 2019 в 05:54
поделиться

Проблема с метаклассом Hao ProperyVoodoo заключается в том, что при наличии нескольких свойств в списке свойств все свойства ведут себя так же, как последнее в списке. Например, если бы у меня был список или имена свойств [«x», «y», «z»], то свойства, сгенерированные для всех трех, использовали бы те же методы доступа, что и «z».

После небольшого эксперимента, я полагаю, я определил, что эта проблема вызвана тем, как Python обрабатывает замыкания (т. Е.имена внутри вложенных функций, которые ссылаются на переменные в содержащей их области). Чтобы решить эту проблему, вам необходимо получить локальные копии переменной имени свойства в методах fget и fset. Достаточно легко скрыть их, используя аргументы по умолчанию:

# (NOTE: Hao's comments removed for brevity)
class PropertyVoodoo(type):

def __init__(cls, *a):

    for prop in cls.__properties__:

        def fget(self, _prop = str(prop)):
            s = super(cls, self)
            return getattr(s, _prop)()


        def fset(self, value, _prop = str(prop)):
            s = super(cls, self)
            return getattr(s, _prop)(value)

        setattr(cls, prop, property(fget=fget, fset=fset))

    super(PropertyVoodoo, cls).__init__(*a)

    def __setattr__(self, name, value):
        if name in cls.__properties__:
            object.__setattr__(self, name, value)
        else:
            s = super(cls, self)
            s.__setattr__(name, value)

    cls.__setattr__ = __setattr__

Обратите внимание, что на самом деле совершенно безопасно давать fget и fset дополнительные параметры _prop, потому что класс property () никогда не будет явно передавать им значения, что означает, что они всегда будет значением по умолчанию (которое является копией строки, на которую ссылается prop во время создания каждого метода fget и fset).

4
ответ дан 30 November 2019 в 05:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: