如何将 `__slots__` 从 Python 2 移植到 3
How to port `__slots__` from Python 2 to 3
我必须将遗留代码(~60K LOC)从 Python 2 移植到 3,它有几千个结构,如下所示:
class Sample(object):
__slots__ = ('both', 'advertise')
class __metaclass__(type):
__instancecheck__ = classmethod(
lambda cls, inst: inst in ('both', 'advertise'))
both = 'both'
advertise = 'advertise'
此代码在 Python 2 上运行良好,但无法在 Python 3 下编译,要解决它,我需要将其更改为
class Sample(object):
__slots__ = ('both', 'advertise')
class __metaclass__(type):
__instancecheck__ = classmethod(
lambda cls, inst: inst in ('both', 'advertise'))
def __init__(self):
both = 'both'
advertise = 'advertise'
考虑到必须对如此大的文件多次执行此更改,处理此更改的有效方法是什么?
我们必须考虑到 class 可能已经有也可能没有 __init__
函数定义,并且也可以有嵌套的 class 定义。
这是我目前尝试过的方法。
2to3
不认为这是一个问题,因此不会更改它。
- 一种可能的方法是使用
ast
模块修改内存中的解析树,然后使用unparse
写回修改后的代码。但这并不简单。
- 如果没有别的办法,我会考虑编写一个简单的 Shell/Python 脚本来读取源文件、进行更改并将其写回。
能否有另一种快速简单的方法来处理此更改。
我不知道有什么比写一个小脚本更好的方法了。我认为这些变化足够小,您可以通过一些不错的启发式方法逃脱,并且不需要 ast
.
的全部功能
但是,如果您有这么多重复的代码,我会从您的代码中完全删除 类。您可以用代码生成器替换它们或为这些 类 编写工厂函数。这将 future-proof 您的代码进行任何更改。
这样的工厂可能是这样的:
class HasStringInstances(type):
def __instancecheck__(cls, instance):
return instance in cls.__slots__
def create_special_class(*slots):
class SpecialClass(object, metaclass=HasStringInstances):
__slots__ = slots
def __init__(self):
for slot in self.__slots__:
# assign name as value
setattr(self, slot, slot)
return SpecialClass
Sample = create_special_class('both', 'advertise')
我必须将遗留代码(~60K LOC)从 Python 2 移植到 3,它有几千个结构,如下所示:
class Sample(object):
__slots__ = ('both', 'advertise')
class __metaclass__(type):
__instancecheck__ = classmethod(
lambda cls, inst: inst in ('both', 'advertise'))
both = 'both'
advertise = 'advertise'
此代码在 Python 2 上运行良好,但无法在 Python 3 下编译,要解决它,我需要将其更改为
class Sample(object):
__slots__ = ('both', 'advertise')
class __metaclass__(type):
__instancecheck__ = classmethod(
lambda cls, inst: inst in ('both', 'advertise'))
def __init__(self):
both = 'both'
advertise = 'advertise'
考虑到必须对如此大的文件多次执行此更改,处理此更改的有效方法是什么?
我们必须考虑到 class 可能已经有也可能没有 __init__
函数定义,并且也可以有嵌套的 class 定义。
这是我目前尝试过的方法。
2to3
不认为这是一个问题,因此不会更改它。- 一种可能的方法是使用
ast
模块修改内存中的解析树,然后使用unparse
写回修改后的代码。但这并不简单。 - 如果没有别的办法,我会考虑编写一个简单的 Shell/Python 脚本来读取源文件、进行更改并将其写回。
能否有另一种快速简单的方法来处理此更改。
我不知道有什么比写一个小脚本更好的方法了。我认为这些变化足够小,您可以通过一些不错的启发式方法逃脱,并且不需要 ast
.
但是,如果您有这么多重复的代码,我会从您的代码中完全删除 类。您可以用代码生成器替换它们或为这些 类 编写工厂函数。这将 future-proof 您的代码进行任何更改。
这样的工厂可能是这样的:
class HasStringInstances(type):
def __instancecheck__(cls, instance):
return instance in cls.__slots__
def create_special_class(*slots):
class SpecialClass(object, metaclass=HasStringInstances):
__slots__ = slots
def __init__(self):
for slot in self.__slots__:
# assign name as value
setattr(self, slot, slot)
return SpecialClass
Sample = create_special_class('both', 'advertise')