Как я могу ссылаться на текущий класс? [Дубликат]

* и ** имеют специальное использование в списке аргументов функции. * подразумевает, что аргумент представляет собой список, а ** подразумевает, что аргумент является словарем. Это позволяет функциям принимать произвольное количество аргументов

18
задан KL. 10 January 2010 в 00:44
поделиться

10 ответов

В Python вы не можете ссылаться на класс в классе, хотя на таких языках, как Ruby, вы можете это сделать.

В Python вместо этого вы можете использовать декоратор класса, но он будет вызываться, как только класс будет инициализируется. Другим способом может быть использование метакласса, но это зависит от того, чего вы пытаетесь достичь.

15
ответ дан A-B-B 28 August 2018 в 08:18
поделиться
  • 1
    Но почему? Что делает класс определения класса отличным от функции-тела в этом отношении? Учитывая, что функции и классы являются объектами первого класса, разница в их телах не сразу очевидна для меня. Изменить: как указывает еще один ответ, тела функции not выполняются при выполнении самого определения, тогда как тела классов выполняются как часть выполнения определения класса. – Dubslow 30 October 2017 в 09:33
  • 2
    Как вы используете декораторы классов и метаклассы для достижения этого? Пример был бы замечательным. – Pro Q 17 December 2017 в 11:56

неа. Он работает в функции, потому что содержимое функции выполняется во время вызова. Но содержимое класса выполняется в time-time, и в этот момент класс еще не существует.

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

class A(object):
    spam= 1

some_func(A)

A.eggs= 2

def _A_scramble(self):
    self.spam=self.eggs= 0
A.scramble= _A_scramble

Однако довольно необычно хотеть вызывать функцию в классе в середине своего собственного определения. Непонятно, что вы пытаетесь сделать, но, скорее всего, вам будет лучше decorators (или относительно новые декодеры класса ).

0
ответ дан bobince 28 August 2018 в 08:18
поделиться

Если вы хотите обратиться к одному и тому же объекту, просто используйте «self»: ​​

class A:
    def some_func(self):
        another_func(self)

Если вы хотите создать новый объект того же класса, просто выполните его:

class A:
    def some_func(self):
        foo = A()

Если вы хотите получить доступ к объекту класса metaclass (скорее всего, не то, что вы хотите), снова выполните его:

class A:
    def some_func(self):
        another_func(A) # note that it reads A, not A()
2
ответ дан carl 28 August 2018 в 08:18
поделиться
  • 1
    Просто пояснение: в вашем последнем примере, ссылаясь на «A», известен как «объект класса», а не «метаклас», что является совершенно иной концепцией. Метакласс А в вашем примере будет types.ClassType (или type при использовании классов нового стиля или python3) – Crast 10 January 2010 в 00:55

Если целью является вызов функции some_func с классом в качестве аргумента, один ответ заключается в объявлении some_func в качестве декоратора класса. Обратите внимание, что декоратор класса вызывается после инициализации класса. Он будет передан классу, который оформляется в качестве аргумента.

def some_func(cls):
    # Do something
    print(f"The answer is {cls.x}")
    return cls # Don't forget to return the class

@some_func
class A:
    x = 1

Если вы хотите передать дополнительные аргументы в some_func, вы должны вернуть функцию из декоратора:

def some_other_func(prefix, suffix):
    def inner(cls):
        print(f"{prefix} {cls.__name__} {suffix}")
        return cls
    return inner

@some_other_func("Hello", " and goodbye!")
class B:
    x = 2

Декораторы классов могут быть скомпонованы, что приводит к их вызыванию в обратном порядке, которые они объявляются:

@some_func
@some_other_func("Hello", "and goodbye!")
class C:
    x = 42

. Результатом является:

# Hello C and goodbye!
# The answer is 42
0
ответ дан cdiggins 28 August 2018 в 08:18
поделиться

Это нормально, чтобы ссылаться на имя класса внутри его тела (например, внутри определения метода), если оно действительно находится в области видимости ... Что будет, если оно определено на верхнем уровне. (В других случаях, вероятно, нет, из-за особенностей Python для определения области видимости!).

Для иллюстрации получения лупы, попробуйте создать экземпляр Foo:

class Foo(object):
    class Bar(object):
        def __init__(self):
            self.baz = Bar.baz
        baz = 15
    def __init__(self):
        self.bar = Foo.Bar()

(Он собирается подать жалобу о глобальном имени «Bar» не определяется.)


Кроме того, что-то говорит мне, что вы можете захотеть изучить методы класса: docs для функции classmethod (to использовать в качестве декоратора), соответствующий вопрос SO . Edit: Хорошо, поэтому это предложение может быть не совсем уместным ... Просто первое, что я подумал, когда читал ваш вопрос, было таким, как альтернативные конструкторы и т. д. Если что-то более простое соответствует вашим потребностям, избегать @classmethod странности. : -)

0
ответ дан Community 28 August 2018 в 08:18
поделиться

В пределах класса не существует способа сделать это, если только A не было определено как-то другим (а затем some_func (A) будет делать что-то совершенно отличное от того, что вы ожидаете)

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

class A:
    # do something
    pass

some_func(A)

То есть, запустите some_func на A после его создания. В качестве альтернативы вы можете использовать декоратор класса (синтаксис для него был добавлен в версии 2.6) или метакласса, если вы хотите каким-то образом изменить класс A. Не могли бы вы пояснить свой прецедент?

1
ответ дан Crast 28 August 2018 в 08:18
поделиться

Если вы хотите сделать небольшую взломанную вещь, сделайте

class A(object):
    ...
some_func(A)

. Если вы хотите сделать что-то более сложное, вы можете использовать метакласс. Метакласс отвечает за манипулирование объектом класса, прежде чем он будет полностью создан. Шаблон должен быть:

class AType(type):
    def __new__(meta, name, bases, dct):
        cls = super(AType, meta).__new__(meta, name, bases, dct)
        some_func(cls)
        return cls

class A(object):
    __metaclass__ = AType
    ...

type является метаклассом по умолчанию. Экземпляры метаклассов являются классами, поэтому __new__ возвращает модифицированный экземпляр (в данном случае) A.

Подробнее о метаклассах см. В http://docs.python.org/reference /datamodel.html#customizing-class-creation.

1
ответ дан Danny Roberts 28 August 2018 в 08:18
поделиться

Вы не можете с конкретным синтаксисом, который вы описываете, из-за времени, когда они оцениваются. Причина, по которой приведенная в примере функция работает, заключается в том, что вызов функции f (i-1) внутри тела функции заключается в том, что разрешение имени f не выполняется до тех пор, пока функция не будет фактически называется. В этот момент f существует в рамках выполнения, так как функция уже была оценена. В случае примера класса ссылка на имя класса просматривается во время определения определения класса. Таким образом, он еще не существует в локальном масштабе.

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

class MetaA(type):

    def __init__(cls):
        some_func(cls)

class A(object):
    __metaclass__=MetaA
  # do something
  # ...

Используя этот подход, вы можете выполнять произвольные операции над объектом класса в то время, когда класс оценены.

7
ответ дан Mark Roddy 28 August 2018 в 08:18
поделиться
  • 1
    Это единственный ответ, объясняющий почему он не может быть выполнен (тела функций не выполняются только при определении, тогда как тела класса). Спасибо за разъяснения. – Dubslow 30 October 2017 в 09:37

Большинство кода в классе будут внутри определения методов, и в этом случае вы можете просто использовать имя A.

-1
ответ дан Ned Batchelder 28 August 2018 в 08:18
поделиться
  • 1
    -1 Он очень конкретно спрашивает о том, чтобы называть А в основной части класса, а не из его методов. – Danny Roberts 10 January 2010 в 03:53

Чего вы хотите достичь? Можно получить доступ к классу, чтобы настроить его определение с помощью метакласса, но это не рекомендуется.

Ваш образец кода может быть написан просто как:

class A(object):
    pass
some_func(A)
0
ответ дан Tobu 28 August 2018 в 08:18
поделиться
Другие вопросы по тегам:

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