Принимает ли setattr / getattr / self .__ dict__ имена атрибутов, которые обычно запрещены? - PullRequest
0 голосов
/ 13 февраля 2019

Я заметил, что хотя это не работает:

class MyClass:
    def __init__(self, i):
        self.5i = i

myobj = MyClass(5)

print(myobj.5i)

Это работает:

class MyClass:
    def __init__(self, i):
        setattr(self, '5i', i)

myobj = MyClass(5)

print(getattr(myobj, '5i'))

Более того, это также работает:

class MyClass:
    def __init__(self, i):
        self.__dict__['i.j'] = i

myobj = MyClass(5)

print(myobj.__dict__['i.j'])

Фрагменты 2 и 3 гарантированно работают?Или, скорее, у нас здесь есть носовые демоны, чей злой план привести невинных душ в ад состоит в том, чтобы заставить махинации такого рода казаться работающими, а на самом деле это не так?

Причина, по которой я спрашиваю, заключается в том, что я преобразую объекты JSON (полученные из API) в классы.И так как сервер любит возвращать дополнительные недокументированные поля, которые иногда кажутся важными, а я не люблю потерять данные ... Это то, что большинство преобразований JSON в объект в настоящее время сводятся к:

class FooResponse:
    def __init__(self, json_string):
        self.__dict__.update(json.loads(json_string))

Но, но ... Что если сервер вернет JSON с некоторыми очень странными полями, например, например:

{
    "foo.bar": "Fizz-Buzz",
    "1337": "speek"
}

Или что-то в этом роде?Нужно ли стараться изо всех сил, чтобы санировать это или просто self.__dict__.update(json.loads(json_string)) подходит?

Серверные документы, принимающие вызовы JSON с именами полей, которые содержат точки или являются строковыми представлениями чисел, поэтому я считаю, что это можетверните также такой JSON.

1 Ответ

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

Атрибут __dict__ - это просто обычный dict, так что да, он разрешает любые ключи, которые допускает обычный dict, которые могут быть любыми объектами, которые можно хэшировать.Однако это не означает, что self.__dict__.update(json.loads(json_string)) является правильным решением, поскольку не только вы не сможете получить доступ к ключам с ненормальными именами с помощью оператора простой точки, но это приведет к неожиданному поведению или даже угрозам безопасности, поскольку объект JSON, чей контент часто извлекается из внешних источников, теперь может переопределять любые атрибуты объекта, включая внутренние, такие как __dict__.Вы должны придерживаться присвоения json.loads(json_string) обычному атрибуту объекта.

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