Есть ли способ изменить класс в методе класса в Python? - PullRequest
0 голосов
/ 03 августа 2009

Я хотел сделать что-то вроде setattr для класса в методе класса в Python, но класс не существует, поэтому я в основном получаю:

NameError: global name 'ClassName' is not defined

Есть ли способ для метода класса изменить класс? Примерно так, но на самом деле это работает:

class ClassName(object):
    def HocusPocus(name):
        setattr(ClassName, name, name)

    HocusPocus("blah")
    HocusPocus("bleh")

Ответы [ 3 ]

5 голосов
/ 03 августа 2009

Методы класса получают класс, переданный в качестве первого аргумента:

class Bla(object):
    @classmethod
    def cm(cls,value):
        cls.storedValue = value

Bla.cm("Hello")

print Bla.storedValue # prints "Hello"

Редактировать : Мне кажется, я понимаю вашу проблему сейчас. Если я правильно понял, все, что вы хотите сделать, это:

class Bla(object):
    storedValue = "Hello again"

print Bla.storedValue # prints "Hello again"

Создание класса в Python (в значительной степени) просто означает:

  1. Создать новое пространство имен.
  2. Запустите код, который вы найдете внутри тела класса, используя это пространство имен
  3. Поместите все, что осталось в пространстве имен, в класс как атрибуты класса.

Поскольку storedValue - это в пространстве имен после шага 2, на шаге 3 он превращается в атрибут класса.

0 голосов
/ 03 августа 2009

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

class ClassName(object):
    def HocusPocus(name):
        setattr(ClassName, name, property(fget=..., fset=...))

    HocusPocus("blah")
    HocusPocus("bleh")

это:

class ClassName(object):

    def HocusPocus(name):
        return property(fget=..., fset=...)

    blah = HocusPocus("blah")
    bleh = HocusPocus("bleh")

Я предполагаю, что загадочным ... отредактированным частям тоже нужен доступ к name (иначе нет необходимости передавать его в качестве аргумента).

Дело в том, что в теле класса HocusPocus по-прежнему является просто функцией (поскольку объект класса еще не существует до тех пор, пока тело класса не завершит выполнение, тело по существу похоже на тело функции, которое выполняется в своем локальном тексте [без оптимизации пространства имен, обычно выполняемой компилятором Python для локальных объектов реальной функции, но это только упрощает семантику!]) и, в частности, она может вызываться в этом теле, может возвращать значение, которому можно присвоить это значение в локальную переменную тела класса, которая станет атрибутом класса в конце выполнения тела) и т. д.

Если вы не хотите, чтобы ClassName.HocusPocus зависал позже, когда вы закончите выполнять его в теле класса, просто добавьте оператор del (например, как последний оператор в теле класса):

    del HocusPocus
0 голосов
/ 03 августа 2009

Еще один способ сделать это - использовать декоратор класса , хотя они доступны только в Python 2.6 и далее IIRC.

Примерно так:

def addattributes(cls):
    cls.foobar = 10
    return cls

@addattributes
class MyClass(object):
    pass

print MyClass.foobar

Этот вид этого наиболее полезен, когда вы хотите «украсить» ряд классов некоторыми специфическими функциями / свойствами. В вашем случае, если вы хотите сделать это только один раз, вы можете просто использовать методы класса, как показано ранее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...