繁体   English   中英

如何将对象存储在动态生成的变量中?

[英]How do I store an object in a dynamically generated variable?

我有一个带有一系列客户端的文本文件。 每行都有一个不同的客户端。 每个客户端都有一个ID,一个用户名和一个密码。

我想创建一个“客户端”类,并在一个循环中在该类中生成对象。 每个对象都有一个用户名和一个密码,并将被存储在包含客户端ID的变量中。 客户端1将存储在“ client_1”中,客户端2将存储在“ client_2”中,依此类推。

我创建了“ read()”方法,该方法打开文本文件,如果有空行则中断,并为每个客户端(每行)检索ID,用户名和密码。

我不知道的是如何做到这一点,以便当客户端的ID为“ 1”时,我为该客户端创建一个对象并将其存储在变量“ client_1”中。 当客户端的ID为“ 2”时,我将客户端的2对象存储在变量“ client_2”中,依此类推。

但是我想自动执行此操作,而不是拥有9000个客户端并自己创建9000个变量。

谢谢

class Client:

    def __init__(self, username, password):
        self.username = username
        self.password = password

    def read(self):
        clients = []
        with open("Clients.txt", "r") as file:
            lines = file.readlines()
            for line in lines:
                if not line:
                    break
                else:
                    client = line.split(" | ")
                    client_id = client[0]
                    #How do I create the variable "client_client[0]"?
                    username = client[1]
                    pre_password = client[2]
                    password = pre_password.strip("\n")
                    #client_client[0] = Client(username, password)
                    clients.append(#client_client[0])
            return clients

我的文本文件(ID,用户名,密码-从左到右):

1 | admin | Z9?zzz
2 | John | J1!jjj
3 | Steve | S1!sss

另外,如果我已经在def init中使用了“ username”和“ password”变量,是否在read()中使用了问题?

谢谢

忠告

  • 在循环中,您正在使用break 不要那样做,您要使用的是continue ,它将跳过此迭代而不是使您脱离迭代。

  • 您仅在密码上使用strip('\\n') 您应该对所有物品都这样做(以确保它们都统一)。 但是您只应在密码情况下使用strip('\\n')是正确的,因为它是唯一具有\\n的密码。 不要将参数放入strip() ,它将处理所有空格,制表符以及其他\\n\\r等。

  • 您应该将类​​的self参数视为位于其中的box 这是您基本上可以在班级各处访问的“环境” 并且,如果您在self内部创建某些内容(例如self.client ,则该名称将与名为client的单个变量不同。 您在这里可能想要做的就是将刚刚读取的客户列表分配给self ,例如self.client_list = self.read()

关于您的程序

您需要做的是创建的变量不如用户那么多 但是您的哲学正确,您想将它们存储在一个地方。 那就是你所做的。 现在,您的程序的要点对我们还是很模糊。 但是您可能想要做的是:

  1. 有一个数据库您可以在其中了解如何订购商品。 您知道,在users_list的每个元素中,都有第一项是id ,第二项是name ,第三项是password

  2. 根据此数据库进行操作。

    • 您要“加载”一个客户端,检查该客户端是否存在于您的数据库中,并将其输入的密码与您链接的密码相匹配!
    • 您要删除一个?
    • 为已经登录的人订购冰淇淋?

您已经拥有的客户列表有什么问题? 您可以作为clients[0]clients[1]等访问客户clients[0] 该列表是任意多个变量的抽象。 列表的索引为0,因此第一个元素的索引为0 这可能会造成混淆,尤其是因为某些语言(例如R,FORTRAN或Wolfram语言)是1索引的。 我不认为这是一个根本性问题,您只需要弄清楚这一点即可。 如果确实困扰您,则可以使用带有数字索引的dict ,然后将想要的任何索引映射到客户。

另外,我会将read_clients免费功能。 它仅使用Client类的公共API进行操作。 因此,它不应该是成员函数。 但是,如果您想在该类中使用它,至少要使其成为@staticmethod ,至少是因为它没有绑定到一个特定的Client

公共API的含义:您编写的每个类都有公共方法和私有方法。 在Python中,没有访问说明符,但是约定是,下划线( _ )开头的方法不能在外部使用。 具有两个下划线的字符(如__init__ )也不能直接调用,而是由语法糖调用。 您希望拥有重点突出的方法( SRP ),因此要使公共功能的数量最少。 还要考虑以下问题:假设有人想使用您的Client类读取带有用户名和密码的其他文件格式。 该人员必须修改您的代码才能添加其他read方法。 但是,如果read_clients函数是外部函数,并且仅使用Client类的__init__ ,则有人可以在某个地方添加一个新的免费函数。 这就是OCP

而且Client可能只是一个collections.NamedTuple 像这样:

import collections

Client = collections.namedtuple('Client', ['username', 'password'])

def read_clients(filename):
    clients = []

    # open file
        # loop over all lines in the list
            # Parse the username and password.
            username = # …
            password = # …
            client = Client(username, password)
            clients.append(client)

    return clients

您不必自己定义Client类,并且所有Client对象(例如client )都将具有属性client.usernameclient.password

使用passwordusername不是问题,因为__init__的参数在不同的范围内。 您班上的成员只能通过self.访问self. ,所以这也不是问题。

如果您真的想动态创建变量,可以使用多种方法, 请参见此处 但是,您再次想要抽象出客户的实际数量,这就是列表的目的。

不要动态创建变量! 而是使用Python的内置字典对象,该对象允许您通过键查找值。

class Client:

    def __init__(self, username, password):
        self.username = username
        self.password = password

def read(file):
    clients = {}
    for line in file:
        if not line:
            continue  # allows blank lines anywhere
        else:
            id, name, password = line.split(" | ")
            password = password.strip("\n")
            clients[id] = Client(name, password)
    return clients

if __name__ == '__main__':
    data = """\
1 | admin | Z9?zzz
2 | John | J1!jjj
3 | Steve | S1!sss
"""
    from io import StringIO
    with StringIO(data) as file:
        clients = read(file)
    for id, client in clients.items():
        print(id, client.username, client.password)

read函数作为类的方法有点令人困惑,因为调用它然后需要您创建一个Client实例才能调用它。 一种替代方法是将其重铸为classmethod ,但是这使事情变得过于复杂,因此作为一个简单函数更有意义。 而不是返回列表,而是返回Client的字典,每个字典都以其各自的id键。

我已经稍微简化了处理过程(尽管仍然没有错误处理),并使循环对空白行更加健壮。

我还添加了一些测试代码,以使您可以验证是否已从测试数据中正确创建了客户端,并在可以选择的情况下使类和函数import可能。 with StringIO(data) as file:替换with StringIO(data) as file:with open("Clients.txt") as file:文件替换:而是使用真实的数据文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM