【问题标题】:How to port `__slots__` from Python 2 to 3如何将“__slots__”从 Python 2 移植到 3
【发布时间】:2017-06-18 01:45:51
【问题描述】:

我必须将遗留代码(~60K LOC)从 Python 2 移植到 Python 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'

鉴于必须对如此大的文件多次执行此更改,什么是处理此更改的有效方法?

我们必须考虑到该类可能已经有也可能没有__init__ 函数定义,并且还可以有嵌套的类定义。

这是我迄今为止尝试过的。

  • 2to3 不认为这是一个问题,因此不会改变它。
  • 一种可能的方法是使用ast 模块修改内存中的解析树,然后使用unparse 写回修改后的代码。但这并不简单。
  • 如果没有其他方法,我将考虑编写一个简单的 Shell/Python 脚本,该脚本将读取源文件、进行更改并将其写回。

能否有另一种快速简单的方法来处理此更改。

【问题讨论】:

  • Metaclasses have changed in Python 3, __metaclass__ 不再起作用。您还可以用一个通用元类替换元类(此处每个类一个),并使用应该适用于所有类的lambda cls, inst: inst in cls.__slots__)
  • 您也可以将__init__中的代码替换为for slot in __slots__: setattr(self, slot, slot)

标签: python python-3.x sed slots python-2to3


【解决方案1】:

我不知道有什么比写一个小脚本更好的方法了。我认为这些变化足够小,您可以通过一些很好的启发式方法摆脱困境,并且不需要ast 的全部功能。

但是,如果您有这么多重复的代码,我会从您的代码中完全删除这些类。您可以将它们替换为代码生成器或为这些类编写工厂函数。这将使您的代码在未来进行任何更改。

这样的工厂可能是这样的:

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')

【讨论】:

  • 谢谢。这听起来像是一个很好的反馈。是的,ast 似乎太重了。此外,ast.NodeVisitor 类中的节点没有指向父节点的指针/链接,因此在解析树中移动节点似乎很困难。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-23
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
相关资源
最近更新 更多