【问题标题】:在类中如何从文件中读取参数?
【发布时间】:2022-01-23 16:08:09
【问题描述】:

假设我有一个这样的 Python 类:

class Person:
  def __init__(self): 
    self.alive = True
    self.name = 'Alice'
    self.age = 20

如何从这个类的外部文件中读取参数?我想它可能类似于以下伪代码:

class Person:
  def __init__(self, filename): 
    self.alive = True                    # same for all persons
    with open(filename, 'r') as f: 
      self.name = f.somehow_read_name    # different for all persons
      self.age = f.somehow_read_age

我可以做到:

alice = Person('alice.txt')
bob = Person('bob.txt')

我希望外部 'alice.txt' 文件是人类可读的,所以可能是这样的:

name = 'Alice' # Name of the person
age  = 20      # Age of the person
### OR ###
{
name : 'Alice', # Name of the person
age  : 20       # Age of the person
}
### OR ###
self.name = 'Alice'
self.age  = 20

参数的顺序很重要。 到目前为止,我一直在这样做:

with open(filename, "r") as f:
  parameters = f.readlines()
  self.name = parameters[8]

当 'alice.txt' 文件中的某些内容发生变化时,这显然是非常繁琐的维护。

【问题讨论】:

  • 您可以使用 yaml 或 ini 作为人类可读的格式。或者自己滚动。否则你的方案是一个好的方案。也可以使用混淆(实际上是任何配置解析器)-confuse.readthedocs.io/en/latest/usage.html 出于完全不同的原因,我们不得不自己做这件事。

标签: python class file-io parameters


【解决方案1】:

此解决方案为人类可读文件创建解析器

代码

class Person:
    def __init__(self, filenm): 
        self.alive = True
        # Get attributes as dictionary
        d = get_attributes_from_file(filenm)

        # Set attributes from dictionary
        for k, v in d.items():
            setattr(self, k, v)

    def __str__(self):
        # Atributes of object as string (to allow printing of object)
        return str(self.__dict__)
        
def get_attributes_from_file(filenm):
    '''
        Parses attribute file
            returns dictionary of attributes
    '''
    
    
    with open(filenm, 'r') as f:
        # Read file contents
        s = f.read()

        # remove comments
        s = ' '.join(x.split('#')[0] for x in s.splitlines())   
        
        # Convert to dictionary
        # uses comma as delimiter
        d = dict([
                    (term.split(':')[0].strip(), term.split(':')[1].strip("' "))
                    for term in s.strip("{}").split(',')
                ])
    
    return d

用法

tom = Person('tom.txt')
dick = Person('dick.txt')
mary = Person('mary.txt')
phyllis = Person('phyllis.txt')

print(tom)  # output: {'alive': True, 'name': 'tom', 'age': '20'}
print(dick) # outptu: {'alive': True, 'name': 'dick', 'age': '25'}
print(mary) # {'alive': True, 'name': 'mary', 'age': '35', 'gender': 'female'}
print(phyllis) # Output: {'alive': True, 'name': 'phyllis', 'age': '35', 'gender': 'female', 'sibling': 'tom'}

文件

tom.txt:

name: tom,            # comment such as this are ignored
age: 20               # age

迪克.txt

name: dick,
age: 25

玛丽.txt

name: 'mary',       # attributes can be with or without quotes
age: 35,
gender: female     # can have extra attributes

phyllis.txt(仅显示注释行和空白行)

name: 'phyllis',
age: 35,   # age in years

gender: female,
#relatives 
sibling: 'tom'

【讨论】:

  • 您的代码能否处理仅注释行,例如tom.txt?
  • @ersbygre1 -- 是的,如我添加的 Phyllis 示例所示。
【解决方案2】:

你有两种方法:

首先,使用 pickle 将您的 python 数据存储在其中并进行检索。使用此链接了解更多信息https://docs.python.org/3/library/pickle.html

其次,您可以使用特定的文件格式来存储和检索您的数据,例如 CSV、JSON、excel 等...。

【讨论】:

  • >> 两种方式....!
【解决方案3】:

我想我找到了一个不错的方法。我试图在课堂上做from alice import *,但没有用(因为*)。但是,只要外部文件被称为 ***.py 并且我将它导入到类中,如下所示:

import alice # if the file is 'alice.py'

然后我可以通过alice.name 等访问该文件中定义的变量并执行以下操作:

import alice
self.name = alice.name
self.age  = alce.age

【讨论】:

  • 我强烈反对在实际项目中使用这种方法。如果在任何时候其他人能够上传或更改文件 alice,那么当您运行 import alice 时,您将运行该文件中的所有代码。这使您面临许多安全漏洞。您可能会争辩说,到目前为止,您信任所有使用您的软件的人,但这可能会在未来发生变化,让这个问题等待发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 2017-05-21
  • 2010-12-15
  • 2015-01-15
  • 2016-10-20
  • 1970-01-01
相关资源
最近更新 更多