为您的对象提供可重现的方式,并可以 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__功能有两个
分开的方法。来自
https://docs.python.org/3/library/functions.html#repr (v 3.7.2)
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定义中)。
可变参数必须以list、
tuple(不需要强制转换)、set或OrderedDict的形式存储在实例中
(集合通过排序呈现)。关键字 args 必须作为dict或OrderedDict存储在实例中。
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在序列化时不会交叉引用对象。虽然pickle和marshal都没有交叉引用, 但renew很可能可以做到,但它是很难说如何让 renew 知道必须在何处以及如何交叉引用一系列对象。
对于功能超强的元编程MacroPy: https ://pypi.org/project/MacroPy/将是一个更好的选择。
有关功能和使用示例的完整列表,请参阅单元测试,尤其是tests/test_renew.py。
项目详情
关
renew- 0.5.4 -py2.py3-none-any.whl 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 73a20b0bb481fe3c17800f67a2b1fb44291759c11fcb4851deac7e613be35add |
|
| MD5 | 538e5052fa501b20e76787668f5288cd |
|
| 布莱克2-256 | 25469d9271720f563ca7aef5febd5bf9ba855a73d1e50474f1215134f16e439b |