Python: как обращаться к классу изнутри (например, рекурсивная функция)
Для рекурсивной функции мы можем сделать:
def f(i):
if i<0: return
print i
f(i-1)
f(10)
Однако есть ли способ сделать следующее:
class A:
# do something
some_func(A)
# ...
Ответы
Ответ 1
В Python вы не можете ссылаться на класс в классе, хотя на таких языках, как Ruby, вы можете это сделать.
В Python вместо этого вы можете использовать декоратор класса, но он будет вызываться после инициализации класса. Другим способом может быть использование метакласса, но это зависит от того, чего вы пытаетесь достичь.
Ответ 2
Вы не можете с определенным синтаксисом, который вы описываете, из-за времени, в которое они были оценены. Причиной приведенной функции примера является то, что вызов функции f (i-1) внутри тела функции состоит в том, что разрешение имени f не выполняется до тех пор, пока функция не будет вызвана. На этом этапе f существует в пределах исполнения, так как функция уже была оценена. В случае примера класса ссылка на имя класса просматривается во время определения определения класса. Таким образом, он еще не существует в локальном масштабе.
В качестве альтернативы желаемое поведение может быть выполнено с использованием метакласса, подобного такому:
class MetaA(type):
def __init__(cls):
some_func(cls)
class A(object):
__metaclass__=MetaA
# do something
# ...
Используя этот подход, вы можете выполнять произвольные операции над объектом класса во время оценки класса.
Ответ 3
Если вы хотите обратиться к одному и тому же объекту, просто используйте "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()
Ответ 4
В пределах класса не существует способа сделать это, если только A не было чем-то другим (а затем some_func (A) будет делать что-то совершенно отличное от того, что вы ожидаете)
Если вы не проводите инспекцию стека для добавления бит в класс, кажется странным, почему вы хотите это сделать. Почему не просто:
class A:
# do something
pass
some_func(A)
То есть, запустите some_func на A после его создания. В качестве альтернативы вы можете использовать декоратор класса (синтаксис для него был добавлен в версии 2.6) или метакласса, если вы хотите каким-то образом изменить класс A. Не могли бы вы пояснить свой вариант использования?
Ответ 5
Неа. Он работает в функции, потому что содержимое функции выполняется во время вызова. Но содержимое класса выполняется в 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
Однако довольно необычно хотеть вызывать функцию в классе в середине своего собственного определения. Непонятно, что вы пытаетесь сделать, но, скорее всего, вам будет лучше с декораторами (или относительно новым декораторы классов).
Ответ 6
Если вы хотите сделать небольшую взломанную вещь,
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.
Ответ 7
Чего вы хотите достичь? Возможно получить доступ к классу, чтобы настроить его определение с помощью метакласса, но это не рекомендуется.
Ваш образец кода может быть написан просто как:
class A(object):
pass
some_func(A)
Ответ 8
Хорошо указывать имя класса внутри его тела (например, определения внутри метода), если оно действительно в области видимости... Которое будет, если оно определено на верхнем уровне. (В других случаях, вероятно, нет, из-за особенностей 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 (для использования в качестве декоратора), соответствующий вопрос SO. Edit: Хорошо, поэтому это предложение может быть не совсем уместным... Просто первое, что я подумал, когда читал ваш вопрос, было таким, как альтернативные конструкторы и т.д. Если что-то более простое соответствует вашим потребностям, избегайте странности @classmethod
,: -)
Ответ 9
Если цель состоит в том, чтобы вызвать функцию 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
Ответ 10
Если я правильно понимаю ваш вопрос, вы сможете ссылаться на класс A внутри класса A, помещая аннотацию типа в кавычки. Это называется прямой ссылкой.
class A:
# do something
def some_func(self, a: 'A')
# ...
См. Ссылку ниже
- https://github.com/python/mypy/issues/3661
- https://www.youtube.com/watch?v=AJsrxBkV3kc
Ответ 11
Большинство кода в классе будут внутри определения методов, и в этом случае вы можете просто использовать имя A
.