【问题标题】:transparent object versioning in pythonpython中的透明对象版本控制
【发布时间】:2012-10-16 16:38:42
【问题描述】:

我想在他们不知情的情况下对对象进行版本化。

类似这样的:

class Versioned(object):
   ...
   def version(self):
       ...

class Foo(Versioned):

   def __init__(self, a):
      self.a = a

foo = Foo(123)
assert foo.version() == 1

foo.a = 1
foo.a = 2
foo.a = 3

assert foo.version() == 4

有简单的方法吗?

【问题讨论】:

  • 你想在这里完成什么?为什么foo.version() 变了?
  • 我认为可以通过覆盖__setattr____delattr__ 来在调用时增加每个实例的计数器来完成类似的操作。但是,我很难想到这会真正有用。
  • @mgilson 因为foo,从版本 1 开始已经更改了 3 次。
  • @senderle,当有多个变更来源时,版本控制会非常有用:)
  • @Srg -- 改变对象的函数呢?这些突变算作每个函数调用 1 个版本,还是每个属性更改 1 个版本?另外,可变对象呢?如果将某些内容附加到列表中,是否要增加版本计数器?

标签: python versioning


【解决方案1】:
class Versioned(object):
    def __init__(self):
        self.version = 0
    def __setattr__(self, name, value):
        if name == 'version':
            object.__setattr__(self, 'version', value)
        else:
            object.__setattr__(self, name, value)
            object.__setattr__(self, 'version', self.version +1)

例子:

class Foo(Versioned):
    pass

f = Foo()
print f.version  # prints 0

f.a = 1
print f.version # prints 1

f.b = 3
print f.version # prints 2

f.b = 33
print f.version # prints 3

【讨论】:

    【解决方案2】:

    快速破解:

    class Versioned(object):
        version = 0
    
        def __init__(self):
            self.version = 0
    
        def _increaseVersion(self):
            super(Versioned, self).__setattr__('version', self.version+1)
    
        def __setattr__(self, attr, value):
            super(Versioned, self).__setattr__(attr, value)
            self._increaseVersion()
    
        def __delattr__(self, attr):
            super(Versioned, self).__delattr__(attr)
            self._increaseVersion()
    
    
    class Foo(Versioned):
        def __init__(self, a):
            self.a = a
            super(Foo, self).__init__()
    
    
    foo = Foo(123)
    print 'value:', foo.a
    print 'version:', foo.version
    foo.a = 23
    print 'value:', foo.a
    print 'version:', foo.version
    del foo.a
    print hasattr(foo, 'a')
    print 'version:', foo.version
    

    输出:

    value: 123
    version: 1
    value: 23
    version: 2
    False
    version: 3
    

    【讨论】:

    • 我喜欢这个更干净的版本,谢谢!最后打电话给super c'tor是个好主意吗?为什么类范围 version 属性?
    • @Srg -- 因为如果您在其他init 代码之前不调用Version.__init__(self),实例将没有version
    • @Srg 类范围是我个人的喜好,因为它使类的自省更加明确(您可以dir(cls) 并查看所有属性而无需实例化它,也可以编写文档工具,如epydoc如果仅在__init__ 中定义属性,则无法显示属性)。最后的super() 调用是将version 初始化为对象属性,因此您可以拥有多个版本的Versioned 类并且版本值不会混淆。
    【解决方案3】:

    请查看https://github.com/swisscom/cleanerversion。如果我正确理解了您的要求,那么它完全符合您的要求。

    由于我们需要一个有点持久的解决方案,因此该模块建立在 Django 之上,允许将这些对象写入任何 Django 支持的关系数据库。

    【讨论】:

      猜你喜欢
      • 2011-12-14
      • 1970-01-01
      • 2022-01-17
      • 2015-11-24
      相关资源
      最近更新 更多