我可能缺乏非常基本的python基础。我正在处理别人制作的脚本。
我有一个脚本,假设是My_Class
,其中代码是:
import thing1
import thing_2
...etc
class My_Class:
def __init__(self, arg1, arg2 ...etc):
self.argument_1 = arg1
self.argument_2 = arg2
...etc
是正确的,my_class有__init__
的参数不作为参数传递给my_class?(my_class没有参数)
如果类没有参数,参数arg1, arg2 ...etc
如何传递给my_class
?
应该是
import thing1
import thing_2
...etc
class My_Class(arg1, arg2 ...etc):
def __init__(self, arg1, arg2 ...etc):
self.argument_1 = arg1
self.argument_2 = arg2
...etc
?
注意:
类不会被实例化,只会直接在类上调用它的方法,即:
My_Class(arg1, arg2 ...etc).method_1()
我希望这些信息能让你更好地理解为什么我们可以调用我们的类,这些参数去哪里,类的形参在哪里等等。
那么,我们来谈谈__call__
:
考虑在类中实现__call__
。它使类的实例可以被调用,换句话说,就是"this"。你能把()
放在实例后面的原因是什么?当您以这种方式调用实例时,__call__
是被调用的实际方法!如果在__call__
方法中将参数定义为参数,则可以在调用实例时传递参数。
class A:
def __call__(self, arg):
print('It is calling', arg)
instance = A()
instance('foo')
现在我们知道类本身是实例——>类型type
:
class A:
pass
print(isinstance(A, type)) # True
所以必须有一个__call__
方法在"their"类(最好说是元类),当然在type
中有一个。这就是为什么我们可以把()
放在类的后面来调用它并向它传递参数。
当你把括号放在你的类前面时,你实际上是在用这里给定的参数arg1
,arg2
…调用type
类的__call__
方法。
等等,但是__init__
在哪里?__new__
在哪里?它们是如何被调用的?
实际上它们在里面被称为类type
的__call__
方法与您传递的参数完全相同。首先是__new__
,如果它返回一个类的实例,那么__init__
就像一个普通的实例方法一样被调用。
现在我将演示我之前解释的内容:(所有类的默认元类是type
类,但我将使用我的元类向您展示详细信息)
class Mymeta(type):
def __call__(cls, *args, **kwargs):
print(f"Metaclass's __call__ gets called with: {args} and {kwargs}")
new_created_instance = cls.__new__(cls, *args, **kwargs)
if isinstance(new_created_instance, cls):
new_created_instance.__init__(*args, **kwargs)
return new_created_instance
class A(metaclass=Mymeta):
def __new__(cls, *args, **kwargs):
# return 10 # <-- If you uncomment this, __init__ won't get called.
return super(A, cls).__new__(cls)
def __init__(self, name, **kwargs):
print(
'This is printed only because'
' we called it inside `__call__` method of the meta class'
)
self.name = name
obj = A('soroush', age=5)
输出:
Metaclass's __call__ gets called with: ('soroush',) and {'age': 5}
This is printed only because we called it inside `__call__` method of the meta class
注意两件事,首先,我们在类前面传递的所有参数都直接传递给元类的__call__
方法。其次,正如您所看到的,Mymeta
的__call__
是__new__
和__init__
的调用者。
你的第一个代码片段是正确的:
class My_Class:
def __init__(self, arg1, arg2 ...etc):
self.argument_1 = arg1
self.argument_2 = arg2
...etc
#Instantiation
c = My_Class(arg1, arg2 ...etc)
#Call method on instance
c.method_1()
你肯定是实例化类:My_Class(arg1, arg2 ...etc)
被python解释为:
- 实例化一个对象
- 调用该对象的
__init__()
(与arg1, arg2…等等)
在python
中,__init__()
方法被认为是其他语言中使用的术语"构造函数"的同义词。
还请注意,在上面的代码片段中,变量c
挂在实例上,这与您的代码片段不同。
TLDR:签名"一个类的属性是由它的__init__
和/或__new__
方法定义的。
class
语句是对元类*的隐式调用。class
语句的任何参数,包括基,都由元类使用。元类负责使用类名、参数和主体来创建实际的类对象。
# v arguments passed to the metaclass
class My_Class(arg1, arg2, ...):
...
值得注意的是,这些是传递给元类的参数。在通常情况下,这些只是基类;只有在高级情况下才需要传递甚至期望其他参数。
当调用一个类时,如My_Class(arg1, arg2, ...)
,它将参数传递给类的__init__
和/或__new__
。因此,__init__
/__new__
定义了一个类的哪些参数。需要.
class My_Class:
# v parameters taken by the class
def __init__(self, arg1, arg2 ...etc):
self.argument_1 = arg1
self.argument_2 = arg2
*这是对元类工作方式的略微简化。有不同层次的间接,而不需要了解全局。