使用python310,我遇到了一些意想不到的事情(但我想这是正常行为).我正在寻找对巨 Python 式设计决定的解释.

我正在try 创建一个类的子类,该类具有在cls.METHOD中指定的稍微自定义的行为

但是,当方法被调用时,它在CLS中被自动传递.从本质上讲,它被视为一个@类方法.(见下文)

我知道我可以将一些_Function作为实例变量传入,并在self.run()中调用它.我的主要问题是why方法,当被调用时,是一个@类方法

def some_function(*args, **kwargs):
    print(args, kwargs)
    print("Why are any args being filled at all?!??!!")

class A(object):
    METHOD = None

    def run(self):
        self.METHOD()
        
        
class B(A):
    METHOD = some_function

# Create an instance and call the run method
instance_of_b = B()
instance_of_b.run()

输出:

(<__main__.B object at 0x7f532970f340>,) {}  
Why are any args being filled at all?!??!!

推荐答案

认为它被视为类方法的假设是错误的;<__main__.B object at 0x7f532970f340>是类的instance,not是类的<class '__main__.B'>.

方法是实例方法by default,需要@staticmethod@classmethod才能偏离该默认设置.*args将以实例方法的实例、类方法的类或静态方法的类开始.因为您没有使用这两个修饰符中的任何一个,所以它被视为一个实例方法,您可以说"自动生成"该实例.

虽然我会说这个模式看起来不是特别讨好,但一个更充实的例子来演示这些差异;(交换B‘S METHOD,看看每个函数的输出是什么样子.)

def some_function(*args, **kwargs):
    print(args, kwargs)

@staticmethod
def some_static_function(*args, **kwargs):
    print(args, kwargs)

def some_instance_function(self, *args, **kwargs):
    print(self, args, kwargs)

@classmethod
def some_class_function(cls, *args, **kwargs):
    print(cls, args, kwargs)

class A(object):
    METHOD = None
    def run(self, *args, **kwargs):
        self.METHOD(*args, **kwargs)
        
class B(A):
    METHOD = some_function

# Demo
instance_of_b = B()
instance_of_b.run("arg",kwarg="kwarg")

你会得到;

  1. some_function
(<__main__.B object at 0x000002ED9340C190>, 'arg') {'kwarg': 'kwarg'}
  1. some_static_function
('arg',) {'kwarg': 'kwarg'}
  1. some_instance_function
<__main__.B object at 0x0000021F3E07C190> ('arg',) {'kwarg': 'kwarg'}
  1. some_class_function
<class '__main__.B'> ('arg',) {'kwarg': 'kwarg'}

最后要考虑的是,将所有这些都考虑在内,并且不得不使用run本身的实例方法格式,这是一个棘手的问题.请注意,如果将其设置为类方法,则some_instance_function个将停止工作.它必须是实例方法,才能允许METHOD根据METHOD想要解释它的方式来解释调用它的self.在run是实例方法的情况下,METHOD可以自由地对调用self做它想做的事情.

另一方面,名称self是约定的;任何名称都可以用于第一个参数.如果在run中使用self的元数令人困惑,您可以将其称为其他名称,即以下代码的工作原理相同.

class A(object):
    METHOD = None
    def run(caller, *args, **kwargs):
        caller.METHOD(*args, **kwargs)

Python-3.x相关问答推荐

Python网页抓取:代码输出:汤未定义

根据样本量随机 Select 组内样本

是否有必要使用Threads()中的args显式地将共享变量传递给Python中的线程函数或直接访问它?

TypeError:&Quot;Value&Quot;参数必须是标量、Dict或Series,但您传递了&Quot;Index&Quot;

十进制浮点数到整型的转换错误

txt 文件与不同的分隔符到整数列表

合并问卷中多列中的稀疏问题 - Pandas

XPATH:使用 .find_elements_by_xpath 为未知数量的 xpath 输入值

有效地缩短列表,直到第一次和最后一次出现不同于 None 的值

获取比较多列的最大值并返回特定值

创建一个可旋转的 3D 地球

Python 3 变量名中接受哪些 Unicode 符号?

python - 错误 R10(启动超时)-> Web 进程未能在启动后 60 秒内绑定到 $PORT

如何将 SimpleGUI 与 Python 2.7 和 3.0 shell 集成

如何在 Python3 中添加带有标志的命令行参数?

AttributeError:系列对象没有属性iterrows

如何将二进制(字符串)转换为浮点值?

无 Python 错误/错误?

混合全局/参数和名为top的函数的奇怪python行为

在 Ipython 中使用 Pylint (Jupyter-Notebook)