纯文本,Python语法文件来保存和恢复一些类变量?



就我而言,我想在文件中保存和恢复一些"普通"变量(即整数,字符串),这些变量最终会成为类属性。这个例子是我得到的最接近的例子,通过使用import

a.py

b = 134
a = "hello"

mytest.py

import inspect
class Teost:
from a import *
def __init__(self):
self.c = 12
print(inspect.getmembers(self)) # has a and b
print(self.__dict__)            # no a and b
print(self.a)                   # prints "hello"
xx = Teost()

所以,这里a.py充当存储变量值(ab)的文件,类内部from a import *将它们作为类属性(self.aself.b),这几乎是我想要的。

不幸的是,事实证明,在类中使用带星标的import语法是不受欢迎的:

$ python mytest.py
mytest.py:3: SyntaxWarning: import * only allowed at module level
class Teost:
[('__doc__', None), ('__init__', <bound method Teost.__init__ of <__main__.Teost instance at 0x7fdca368ab90>>), ('__module__', '__main__'), ('a', 'hello'), ('b', 134), ('c', 12)]
{'c': 12}
hello

。所以我得到一个丑陋的"语法警告:导入*只允许在模块级别",我无法摆脱(除非我禁用警告,我不想这样做)

那么,我还有其他选择,使用以a.py编写的文件(即纯文本,Python 语法),并让其中的变量最终成为一些类属性?

(我已经看过如何在 python 中保存和恢复多个变量?,但我对pickleshelve不感兴趣,因为它们都没有用 Python 语法、纯文本文件编写)

您可以将模块导入到类中,如下所示:

法典:

class Teost:
import a as _a_py_attrs
def __init__(self):
for name in dir(Teost._a_py_attrs):
if not name.startswith('__'):
setattr(self, name, getattr(Teost._a_py_attrs, name))

测试代码:

xx = Teost()
print(xx.__dict__)
print(xx.a)

结果:

{'a': 'hello', 'b': 134}
hello

作为类属性:

如果最好将这些作为类属性而不是实例属性,则可以执行以下操作:

class Teost:
""" My Test Class """
import a as _a_py_attrs
for name in dir(_a_py_attrs):
if not name.startswith('__'):
setattr(Teost, name, getattr(_a_py_attrs, name))

测试代码:

xx = Teost()
print(xx.__dict__)
print(xx.a)

结果:

{}
hello

我的意思是,你可以做一些超级黑客的事情:

import inspect
import a
class A:
def __init__(self):
self.c = 12
print(('a', 'hello')  in inspect.getmembers(self)) # has a and b
print(('b', 134) in inspect.getmembers(self))
print('a' in self.__dict__)            # no a and b
print('b' in self.__dict__)
print(self.a)                   # prints "hello"
for name in dir(a):
if not name.startswith('__'): # very brittle here
val = vars(a)[name]
setattr(A, name, val)
x = A()

您可能希望将上述逻辑包装在元类中。

也许只使用exec更干净。如果您信任a.py的来源,这应该不是太大的问题。

好吧,找到了一个解决方法(不会引发错误或警告) - 而不是import,读取文件,然后exec(不是eval,评估语法错误:python中的语法无效)它:

#from a import *
with open('a.py') as x: fstr = x.read()
exec(fstr)

。虽然我可能应该对使用exec感到不舒服......

最新更新