如果类没有形参,如何将实参传递给类?



我可能缺乏非常基本的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解释为:

  1. 实例化一个对象
  2. 调用该对象的__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

*这是对元类工作方式的略微简化。有不同层次的间接,而不需要了解全局。

最新更新