Skip to main content

为您的对象提供可重现的方式,并可以 100% pythonic 格式序列化它们。

项目描述

纯python中的半文本酸洗。
如果你只满足一些限制,你可以存储类
将状态写入 python 文件并在某处导入或评估它
否则或以后。您甚至可以将其用作数据库,除非
数据量巨大。

1 分钟 - 示例:

import renew

class ThatNiceClass(renew.Mold):
    # manual implementation of __init__ is needed. Constructor_arguments
    # have to be actual names of this class attributes
    def __init__(self, f_a, f_b, *f_c, **f_d):
        self.f_a, self.f_b, self.f_c, self.f_d = f_a, f_b, f_c, f_d

c = ThatNiceClass(1, 2, 3, 4, five=5, six=6)

assert repr(c) == "ThatNiceClass(1, 2, 3, 4, five=5, six=6)"
assert c == eval(repr(c))  # __eq__ implemented
assert repr(c) == repr(eval(repr(c)))  # pure reproduction, instance "survives" eval

class SecondClass(renew.Mold):
    _cls_namespace = "foo_pkg"

    def __init__(self, one, two="number two", three=None):
        self.one, self.two, self.three = one, two, three

s1 = SecondClass(1)
s2 = SecondClass(3.14159, "non default")
s3 = SecondClass("Lorem ipsum dolor sit amet, consectetur adipiscing elit")
s4 = SecondClass(4, three=ThatNiceClass(1, 2, 3, 4, five=5, six=6))

d = ThatNiceClass(s1, s2, lorem=s3, im_nesting=s4)

assert repr(d) == """\
ThatNiceClass(
    foo_pkg.SecondClass(1),
    foo_pkg.SecondClass(3.14159, 'non default'),
    im_nesting=foo_pkg.SecondClass(4, three=ThatNiceClass(1, 2, 3, 4, five=5, six=6)),
    lorem=foo_pkg.SecondClass('Lorem ipsum dolor sit amet, consectetur adipiscing elit'),
)"""

__repr__故事 - repr(object )

repr代表“表示”还是“复制”?
根据 python 文档__repr__功能有两个
repr(object)返回一个包含对象的可打印表示的字符串。
对于许多类型,此函数会尝试返回一个字符串
这将在传递给 eval() 时产生具有相同值的对象,
否则表示是用尖括号括起来的字符串
包含对象类型的名称以及
附加信息通常包括姓名和地址
物体。一个类可以控制这个函数返回什么
它的实例通过定义一个__repr__()方法。

1.可重现的repr:

对于几个本机对象,它返回一个可以使用的字符串
复制给定对象,即创建给定对象的副本。
a = [1, 3.141559, None, "string"]
statement_str = repr(a)
assert statement_str == '[1, 3.141559, None, "string"]'

如果满足以下条件,您可能会说对象的 repr 是可重现的:

a = [1, 3.14159, None, "string"]
statement_str = repr(a)
assert repr(eval(statement_str)) == statement_str
# if the object implements __eq__ this should be also true:
assert eval(statement_str) == a

2.描述性repr:

不幸的是,python 不提供开箱即用的“可重现的 repr”
对于用户定义的类型:
class Car(object):
    def __init__(self, body_type, engine_power):
        self.body_type = body_type
        self.engine_power = engine_power

car = Car("coupe", 124.0)
# repr(car) == '<__main__.Car object at 0x7f0ff6313290>'
# but using renew:

import renew

class ReproducibleCar(renew.Mold):
    _cls_namespace = "bar"
    def __init__(self, body_type, engine_power):
        self.body_type = body_type
        self.engine_power = engine_power

car2 = ReproducibleCar("sedan", 110.0)
assert repr(car2) == 'bar.ReproducibleCar("sedan", 110.0)'

上面的方法是作为装饰器实现的,但您也可以使用继承来获得相同的结果。

import renew

class Car(renew.Mold):
    _cls_namespace = "cars"
    _cls_dependency = "that.things"

    def __init__(self, body_type, engine_power, fuel, seats, color=None):
        self.body_type = body_type
        self.engine_power = engine_power
        self.fuel = fuel
        self.seats = seats
        self.color = color

class Driver(renew.Mold):
    _cls_namespace = "persons"

    def __init__(self, first_name, last_name, *cars):
        self.first_name = first_name
        self.last_name = last_name
        self.cars = cars

car_1 = Car("Truck", 120.0, "diesel", 2)
car_2 = Car("Van", 145.0, "diesel", seats=7, color="silver")
car_3 = Car("Roadster", 210.0, "gasoline", seats=2)

driver_1 = Driver("Blenda", "Klapa", car_1)
driver_2 = Driver("Trytka", "Blotnick", car_2, car_3)

assert repr(driver_1) == ".Driver('Blenda', 'Klapa', cars.Car('Truck', 120.0, 'diesel', 2))"
assert repr(driver_2) == """\
persons.Driver(
    'Trytka',
    'Blotnick',
    cars.Car('Van', 145.0, 'diesel', 7, 'silver'),
    cars.Car('Roadster', 210.0, 'gasoline', 2),
)"""

renew.serialize("/tmp/target.py", blenda=driver_1, trytka=driver_2)

创建的文件如下所示:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This file has been created with renew.
# A py-pickling tool: https://pypi.org/project/renew/

from living.things import persons
from that.things import cars

blenda = persons.Driver('Blenda', 'Klapa', cars.Car('Truck', 120.0, 'diesel', 2))

trytka = persons.Driver(
    'Trytka',
    'Blotnick',
    cars.Car('Van', 145.0, 'diesel', 7, 'silver'),
    cars.Car('Roadster', 210.0, 'gasoline', 2),
)

这个怎么运作?

请注意,ReproducibleCar没有显式实现 __repr__,而是renew.reproducible
装饰器补充它(如果之前定义过,则覆盖它)。
renew.reproduction检查构造函数的参数规范
装饰类并产生一个字符串,该字符串试图成为由以下组成的调用语句
  • namespace,例如您的包名(根据所需的导入约定)

  • 给定的类名

  • 给定类的属性值,与构造函数参数具有相同的名称和顺序

这形成了唯一的一个使用限制:

该类必须将所有构造函数参数存储在其具有相同名称的属性中(如上面的ReproducibleCar定义中)。

可变参数必须以listtuple(不需要强制转换)、setOrderedDict的形式存储在实例中
(集合通过排序呈现)。关键字 args 必须作为dictOrderedDict存储在实例中。
from collections import OrderedDict
import renew

class ThatClass(renew.Mold):
    def __init__(self, x=1, *others, **kw_args):
        self.x = x
        self.others = OrderedDict(others)
        self.kw_args = kw_args

that = ThatClass(3.14159, ("a", "A"), ("b", "B"), one=1, two=2, many=666)

assert repr(that) == "ThatClass(3.14159, many=666, one=1, two=2)"
assert that.x == 3.14159
assert that.others == OrderedDict([("a", "A"), ("b", "B")])
assert that.kw_args == dict(one=1, two=2, many=666)

限制

  • 如果给定键的 repr 跨越多行,则普通dict的键是“复杂”对象的布局会有点难看。

  • renew在序列化时不会交叉引用对象。
    虽然picklemarshal都没有交叉引用, 但renew很可能可以做到,但它是
    很难说如何让 renew 知道必须在何处以及如何交叉引用一系列对象。
  • 对于功能超强的元编程MacroPyhttps ://pypi.org/project/MacroPy/将是一个更好的选择。

有关功能和使用示例的完整列表,请参阅单元测试,尤其是tests/test_renew.py

下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

内置分布

renew-0.5.4-py2.py3-none-any.whl (16.1 kB 查看哈希

已上传 py2 py3