gpt4 book ai didi

python - 在没有实例化的情况下订购类方法

转载 作者:行者123 更新时间:2023-11-28 17:38:47 25 4
gpt4 key购买 nike

相关:inspect.getmembers in order?

背景:我正在尝试构建一个根据特定规范创建 Python 文件的工具。一种选择是提供一个包含抽象类声明的 Python 模块作为输入,并创建一个继承该抽象类的基类,同时为所有抽象方法添加一个默认实现。

例如:假设我有以下文件,名为 Abstract.py,其中包含以下内容:

class Abstract(object):
__metaclass__ = ABCMeta
@abstractmethod
def first(self):
pass
@abstractmethod
def second(self):
pass

那么我的工具的输出将是一个名为 BaseClass.py 的文件,其中包含:

class BaseClass(Abstract):
def first(self):
pass
def second(self):
pass

我希望 BaseClass 中的方法与 Abstract 中的方法顺序相同。

我的问题是:有没有一种方法可以根据方法的外观对方法进行排序,而不依赖于内置方法比较(基于内存地址比较)?如果可能的话,我也希望避免任何类型的文件解析。

请注意,我无法创建Abstract 的实例,所以上面提到的解决方案related question对我不起作用。

最佳答案

在 Python2 中创建类时(也就是说,当解释器在运行文件时只传递类主体时,这是按顺序发生的)——类本身被创建为一个对象。此时,类主体中定义的所有变量和方法都作为字典传递给对“type”(默认元类)的调用。

如您所知,Python 中的字典没有顺序,因此通常在 Python2 中是不可能的。这在 Python 3 中是可能的,因为元类可以实现 __prepare__ 方法,该方法返回将用于构建类主体的映射对象 - 所以不是普通的字典,__prepare__可以返回一个 OrderedDict。

但是,在您的情况下,所有相关方法都用 @abstractmethod 装饰 - 我们可以利用它不仅将方法注释为抽象方法,还可以标记它们出现的顺序.

您可以包装 abstractclass 装饰器,或者创建另一个装饰器并同时使用两者。我更喜欢一个新的装饰器,它可以做这两件事,以减少行数。

此外,您还必须选择您将如何保持方法的顺序并使用它。通常迭代类的属性只会迭代字典(而不是字典代理),它是无序的 - 因此,您必须保留数据结构以保持有序方法可用,以及记录此给定顺序的方法。那里有一些选项 - 但也许,最直接的事情是在方法本身中注释方法顺序,并通过调用内置 sorted 和适当的 key 来检索它们 参数。其他方法需要类装饰器或自定义元类才能工作。

所以这是我写的一个例子:

from abc import abstractmethod, ABCMeta

class OrderedAbstractMethod(object):
def __init__(self):
self.counter = 0
def __call__(self,func):
func._method_order = self.counter
self.counter += 1
return abstractmethod(func)

ordered_abstract_method = OrderedAbstractMethod()



class Abstract(object):
__metaclass__ = ABCMeta
@ordered_abstract_method
def first(self):
pass
@ordered_abstract_method
def second(self):
pass
@ordered_abstract_method
def third(self):
pass
@ordered_abstract_method
def fourth(self):
pass


print "Unordered methods: ",[method[0] for method in Abstract.__dict__.items() if not method[0].startswith("_") ]
# here it printed out - ['second', 'third', 'fourth', 'first']

print "Ordered methods: ", sorted([method for method in Abstract.__dict__.items() if not method[0].startswith("_") ], key= lambda m: m[1]._method_order)

关于python - 在没有实例化的情况下订购类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27484464/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com