#python
#python
Вопрос:
Пользовательские данные следующим образом:
user = {"id": 1, "firstName": "Bar", "surname": "Foosson", "age": 20}
отправляется в приложение через json.
Во многих местах кода это сделано следующим образом:
user["firstName"] " " user["surname"]
что наводит меня на мысль, что следует использовать функцию:
def name(user):
return user["firstName"] " " user["surname"]
что, в свою очередь, наводит меня на мысль, что код должен быть переработан с использованием User
класса вместо name
метода. Согласны ли вы и есть ли какие-либо аргументы в пользу того, чтобы не проводить рефакторинг кода для использования класса вместо этого?
Комментарии:
1. В сторону, используйте
"{firstName} {surname}".format(**user)
. 😉2. Еще один аспект: в Python эти вещи называются «dicts» (их тип
dict
); называть их «maps» может сбивать с толку (из-заmap
).3. Я бы использовал класс, даже если в этом не было необходимости
def name(user)
. Как правило, если ключиdict
фиксированы (вы всегда ожидаете иметь имя, фамилию), это указывает на то, что вам, вероятно, не следует использоватьdict
.4. @Bhargav Rao Что, если кто-то случайно написал «{FirstName} {фамилия}».format(** user), где случайно есть два пробела между «}» и «{«? Конечно user.name () лучше.
5. @Baz что, если кто-то случайно написал два пробела
" "
? Конечно, Бхаргав прав. Будь как Бхаргав.
Ответ №1:
Я уверен, что вы не решаетесь использовать классы из-за необходимости писать шаблонный код.
Но есть хорошая библиотека, которая может облегчить вашу жизнь : attrs
.
В Glyph есть сообщение с говорящим названием: единственная библиотека Python, которая нужна всем. Конечно, это самоуверенная статья, но вот цитата со страницы примеров:
>>> @attr.s ... class Coordinates(object): ... x = attr.ib() ... y = attr.ib()
По умолчанию добавляются все функции, поэтому у вас сразу же появляется полностью функциональный класс данных с хорошей
repr
строкой и методами сравнения.>>> c1 = Coordinates(1, 2) >>> c1 Coordinates(x=1, y=2) >>> c2 = Coordinates(x=2, y=1) >>> c2 Coordinates(x=2, y=1) >>> c1 == c2 False
Это довольно удобная библиотека, так что проверьте ее.
Вот пример вашего User
класса:
import attr
@attr.s
class User(object):
id = attr.ib()
firstName = attr.ib()
surname = attr.ib()
age = attr.ib()
@property
def name(self):
return '{0.firstName} {0.surname}'.format(self)
user_dict = {'id': 1, 'firstName': 'Bar', 'surname': 'Foosson', 'age': 20}
user = User(**user_dict)
assert user.name == 'Bar Foosson'
Ответ №2:
Словари отлично подходят для хранения и поиска, но если вам нужно больше функциональности, обычно лучше использовать класс. Таким образом, вы также можете убедиться, что определенные атрибуты установлены и т.д.
В вашей ситуации, если атрибуты пользователя доступны только для чтения, мой подход действительно будет использовать namedtuple
. Вы получаете неизменность атрибутов, эффективность использования памяти, и вы все равно можете установить name
предварительно определенный метод, который будет использоваться точно так же, как вы бы использовали property
в классе:
from collections import namedtuple
@property
def name(self):
return '{} {}'.format(self.firstName, self.surname)
User = namedtuple('User', 'id firstName surname age')
User.name = name
user = User(1, 'Bar', 'Foosson', 20)
print(user.name) # Bar Foosson
user = User(2, 'Another', 'Name', 1)
print(user.name) # Another Name