Как мне сохранить объект в динамически генерируемой переменной? - PullRequest
0 голосов
/ 09 февраля 2019

У меня есть текстовый файл с серией клиентов.У каждой строки есть свой клиент.У каждого клиента есть идентификатор, имя пользователя и пароль.

Я хочу создать класс «Клиент» и сгенерировать объекты в этом классе в цикле.Каждый объект будет иметь имя пользователя и пароль и будет храниться в переменной, содержащей идентификатор клиента.Клиент 1 будет храниться в «client_1», Клиент 2 будет храниться в «client_2» и т. Д.

Я создал метод «read ()», который открывает текстовый файл, прерывает, если есть пустые строки,и извлекает идентификатор, имя пользователя и пароль для каждого клиента (каждой строки).

Я не могу понять, как сделать так, чтобы, когда идентификатор клиента был «1», я создавал объектдля этого клиента и сохраните его в переменной «client_1».Когда идентификатор клиента равен «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

Кроме того, есть ли проблема, еслиЯ использую переменные "username" и "password" в read (), когда я уже использовал их в def init ?

Спасибо

Ответы [ 3 ]

0 голосов
/ 09 февраля 2019

Советы

  • В вашем цикле вы используете 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. Выполните операциина основе этой базы данных .

    • Вы хотите «загрузить» клиента, проверить, существует ли он в вашей базе данных, и сопоставить введенный им пароль с тем, с которым вы связались!
    • Вы хотитеудалить один?
    • Заказать мороженое для того, кто уже вошел в систему?
0 голосов
/ 09 февраля 2019

Не создавайте переменные динамически!Вместо этого используйте встроенный в 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 s, каждый из которых имеет свой соответствующий id.

. Я несколько упростил обработку (хотя обработка ошибок по-прежнему отсутствует) и сделалболее устойчивый цикл к пустым строкам.

Я также добавил немного тестового кода, чтобы вы могли проверить, правильно ли были созданы клиенты из ваших тестовых данных, и чтобы ваш класс и функция import моглиесли вы выберете.Замените with StringIO(data) as file: на with open("Clients.txt") as file:, чтобы использовать вместо него реальный файл данных.

0 голосов
/ 09 февраля 2019

Что не так с тем списком клиентов, который у вас уже есть?Вы можете получить доступ к клиентам как clients[0], clients[1] и так далее.Список является абстракцией для произвольного множества переменных.Списки индексируются 0, поэтому первый элемент имеет индекс 0.Это может сбивать с толку, особенно потому, что некоторые языки, такие как R, FORTRAN или Wolfram Language, индексируются 1.Я не считаю это фундаментальной проблемой, вам просто нужно прояснить ситуацию.Если это действительно беспокоит вас, вы можете использовать dict с числовыми индексами и просто сопоставить любой индекс, который вы хотите, с клиентом.

Также я бы сделал read_clients бесплатной функцией.Он не использует ничего, кроме открытого API класса Client для работы.Поэтому он не должен быть функцией-членом.Но если вы хотите, чтобы он был в этом классе, сделайте его @staticmethod хотя бы потому, что он не привязан к одному конкретному Client.

Что я имею в виду с открытым API: каждый класс, который вы пишете, имеетпубличные методы и частные методы.В Python нет спецификаторов доступа, но соглашение состоит в том, что методы, начинающиеся с подчеркивания (_), не должны использоваться извне.Те, которые имеют два подчеркивания (например, __init__), также не должны вызываться напрямую, а называются синтаксическим сахаром.Вы хотите иметь целенаправленные методы ( SRP ), поэтому используйте как можно меньше открытых функций.Также учтите следующее: скажем, кто-то хочет использовать ваш класс Client для чтения файлов другого формата с именами пользователей и паролями.Этот человек должен будет изменить ваш код , чтобы добавить еще один метод read.Но если функция read_clients была внешней и просто использовала __init__ вашего Client класса, то кто-то мог бы просто добавить новую свободную функцию где-нибудь.Это 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.username и client.password.

Использование password и username не является проблемой, поскольку параметр __init__ находится в другой области видимости.Доступ к членам вашего класса возможен только через self., так что это тоже не проблема.

Если вы действительно хотели динамически создавать переменные, есть способы сделать это, см. Здесь .Но опять же, вы хотите абстрагироваться от фактического количества клиентов, и для этого предназначен список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...