简体   繁体   English

如何将__slots__从Python 2移植到3

[英]How to port `__slots__` from Python 2 to 3

I have to port a legacy code ( ~60K LOC) from Python 2 to 3 which has a couple of thousand of structures like below: 我必须将旧代码(〜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'

This code works fine with Python 2 but doesn't compile with Python 3 and to resolve it I need to change it to 该代码在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'

What would be an efficient way to handle this change given that it has to be done over such a large file multiple times? 鉴于必须在如此大的文件上多次执行此更改,因此什么是处理此更改的有效方法?

We have to consider that there may or may not be a __init__ function definition already for the class and there can be nested class definitions as well. 我们必须考虑到该类可能已经或可能没有__init__函数定义,并且也可能存在嵌套的类定义。

This is what I have tried so far. 到目前为止,这是我尝试过的。

  • 2to3 doesn't recognize this as an issue and hence doesn't change it. 2to3不会将此视为问题,因此不会更改。
  • One possible way could be to use ast module to modify the parse tree in memory and then use unparse to write back the modified code. 一种可能的方法是使用ast模块修改内存中的解析树,然后使用unparse来写回修改后的代码。 But it is not straightforward. 但这并不简单。
  • If nothing else works, I will consider writing a simple Shell/Python script which will read the source file, make changes and write it back. 如果没有其他效果,我将考虑编写一个简单的Shell / Python脚本,该脚本将读取源文件,进行更改并将其写回。

Can there be another quick and simple way to handle this change. 是否有另一种快速简单的方法来处理此更改。

I don't know of any better way than to write a small script. 我不知道有什么比编写小型脚本更好的方法了。 I think the changes are small enough that you can get away with some nice heuristics and don't need the full power of ast . 我认为变化很小,您可以通过一些不错的启发法来解决,并且不需要ast的全部功能。

However, if you have this much repetition of code, I would remove the classes from your code altogether. 但是,如果您有如此多的代码重复,我将完全从您的代码中删除这些类。 You can replace them with either a code generator or write a factory function for these classes. 您可以用代码生成器替换它们,也可以为这些类编写工厂函数。 This is going to future-proof your code for any changes. 这将使您的代码在将来可以进行任何更改。

Such a factory could look like this: 这样的工厂可能看起来像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM