Python 没有实例化的类方法排序
相关的: 背景:我正在尝试构建一个工具,根据特定规范创建Python文件。一个选项是作为输入提供一个包含抽象类声明的Python模块,并创建一个基类,该基类继承该抽象类,但也向所有抽象方法添加一个默认实现 例如:假设我有一个名为Python 没有实例化的类方法排序,python,python-2.7,Python,Python 2.7,相关的: 背景:我正在尝试构建一个工具,根据特定规范创建Python文件。一个选项是作为输入提供一个包含抽象类声明的Python模块,并创建一个基类,该基类继承该抽象类,但也向所有抽象方法添加一个默认实现 例如:假设我有一个名为Abstract.py的文件,其中包含以下内容: class Abstract(object): __metaclass__ = ABCMeta @abstractmethod def first(self): pass @
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
我希望基类
中的方法与摘要
中的方法顺序相同
我的问题是:有没有一种方法可以根据方法的外观对其进行排序,而不依赖于内置的方法比较(基于内存地址比较)?如果可能的话,我也希望避免任何类型的文件解析
请注意,我无法创建
Abstract
的实例,因此上面提到的解决方案对我来说不起作用。在Python2中创建类时(即,当解释器在运行文件时刚刚通过类体时,按顺序进行)-类本身被创建为对象。此时,类主体中定义的所有变量和方法都作为字典传递给对“type”(默认元类)的调用
正如您所知,Python中的字典没有顺序,所以通常在Python 2中是不可能的。在Python3中,这是可能的,因为元类可以实现一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,该方法返回将用于构建类主体的映射对象,因此,而不是普通dict,\uuuuuu
但是,在您的例子中,所有相关的方法都用@abstractmethod
修饰-我们可以利用这一点,不仅将方法注释为抽象,而且还可以标记它们出现的顺序
您可以包装抽象类
装饰器,或者创建另一个装饰器并同时使用这两个装饰器。我希望有一个新的装饰师能同时做这两件事,以减少排队次数
此外,您还必须选择如何保持方法的顺序并加以利用。通常,对类的属性进行迭代只会在字典(而不是字典代理)上进行迭代,这是无序的-因此,为了保持有序方法可用,您必须保持数据结构,以及记录给定顺序的方法。这里有一些选项,但最直接的方法可能是在方法本身中注释方法顺序,并通过调用内置的sorted
和适当的键
参数来检索它们。其他方法需要类装饰器或自定义元类才能工作
下面是我写的一个例子:
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)
有趣的方法。一个缺点是,这意味着我必须继续并更改所有我希望与之一起使用的抽象方法的所有签名。尽管如此,这可能是最好的方法……如果已经有很多类,您也可以调用您的decorator“abstractmethod”,然后从上面定义的地方导入它。