Я использую следующий класс, чтобы легко хранить данные моих песен.
class Song:
"""The class to store the details of each song"""
attsToStore=('Name', 'Artist', 'Album', 'Genre', 'Location')
def __init__(self):
for att in self.attsToStore:
exec 'self.%s=None'%(att.lower()) in locals()
def setDetail(self, key, val):
if key in self.attsToStore:
exec 'self.%s=val'%(key.lower()) in locals()
Я чувствую, что это гораздо более расширяемо, чем запись if/else
блока. Тем не менее, eval
кажется, считается плохой практикой и небезопасно использовать. Если так, может кто-нибудь объяснить мне, почему и показать мне лучший способ определения вышеупомянутого класса?
exec/eval
и до сих пор не зналsetattr
?Ответы:
Да, использование eval - плохая практика. Просто назвать несколько причин:
В вашем случае вы можете использовать setattr вместо:
РЕДАКТИРОВАТЬ:
В некоторых случаях вы должны использовать eval или exec. Но они редки. Использование eval в вашем случае наверняка плохая практика. Я подчеркиваю плохую практику, потому что eval и exec часто используются не в том месте.
РЕДАКТИРОВАТЬ 2:
Похоже, что некоторые не согласны с тем, что eval является «очень опасным и небезопасным» в случае с OP. Это может быть верно для этого конкретного случая, но не в целом. Вопрос был общим, и причины, которые я перечислил, верны и для общего случая.
РЕДАКТИРОВАТЬ 3: Изменение порядка пунктов 1 и 4
источник
eval
имеет ничего общего друг с другом. Приложение, которое в корне неправильно спроектировано, в корне неправильно спроектировано.eval
является не более чем основной причиной плохого дизайна, чем деление на ноль или попытка импортировать модуль, который, как известно, не существует.eval
не небезопасно Приложения небезопасны.calc
, и для добавления чисел она выполняетсяprint(eval("{} + {}".format(n1, n2)))
и выходит. Теперь вы распространяете эту программу с некоторыми ОС. Затем кто-то делает скрипт bash, который берет некоторые цифры со стокового сайта и добавляет их, используяcalc
. бум?Использование
eval
слабое, не совсем плохая практика.Это нарушает «Фундаментальный принцип программного обеспечения». Ваш источник не является общей суммой исполняемого файла. Помимо вашего источника, есть и аргументы
eval
, которые должны быть четко поняты. По этой причине это инструмент последней инстанции.Обычно это признак бездумного замысла. Там редко бывают веские причины для динамического исходного кода, созданного на лету. Почти все может быть сделано с делегированием и другими методами проектирования ОО.
Это приводит к относительно медленной на лету компиляции небольших фрагментов кода. Накладные расходы, которых можно избежать, используя лучшие шаблоны проектирования.
В качестве сноски, в руках ненормальных социопатов, это может не сработать. Однако, когда сталкиваешься с ненормальными социопатическими пользователями или администраторами, лучше не давать им интерпретируемый Python. В руках действительно зла, Python может быть ответственностью;
eval
не увеличивает риск вообще.источник
eval
это какая-то «уязвимость безопасности». Как будто Python - сам по себе - не просто набор интерпретируемого источника, который любой может изменить. Столкнувшись с «eval - это дыра в безопасности», вы можете только предполагать, что это дыра в безопасности в руках социопатов. Обычные программисты просто модифицируют существующий исходный код Python и напрямую вызывают свои проблемы. Не косвенно черезeval
магию.while True: pass
было бы трудно убрать с каким-то побегом.eval()
, так как это строка. Код из «внешнего мира» не может быть санирован. Струны из внешнего мира - это просто струны. Мне неясно, о чем ты говоришь. Возможно, вы должны предоставить более полный пост в блоге и ссылку на него здесь.В этом случае да. Вместо того
Вы должны использовать встроенную функцию
setattr
:источник
Да, это так:
Взломать с помощью Python:
В приведенном ниже коде перечислены все задачи, выполняемые на компьютере под управлением Windows.
В Linux:
источник
Стоит отметить, что для решения конкретной проблемы есть несколько альтернатив использования
eval
:Самым простым, как уже отмечалось, является использование
setattr
:Менее очевидный подход - это
__dict__
непосредственное обновление объекта. Если все, что вы хотите сделать, это инициализировать атрибутыNone
, то это не так просто, как указано выше. Но учтите это:Это позволяет передавать ключевые аргументы в конструктор, например:
Это также позволяет сделать использование
locals()
более явным, например:... и, если вы действительно хотите назначить
None
атрибуты, имена которых находятся вlocals()
:Другой подход к предоставлению объекта со значениями по умолчанию для списка атрибутов заключается в определении
__getattr__
метода класса :Этот метод вызывается, когда именованный атрибут не найден обычным способом. Этот подход несколько менее прост, чем просто установка атрибутов в конструкторе или обновление
__dict__
, но он имеет преимущество в том, что фактически не создает атрибут, если он не существует, что может значительно уменьшить использование памяти классом.Суть всего этого: в общем, есть много причин, которых следует избегать
eval
- проблема безопасности выполнения кода, который вы не контролируете, практическая проблема кода, который вы не можете отлаживать, и т. Д. Но еще более важная причина это вообще, вам не нужно его использовать. Python предоставляет так много своих внутренних механизмов программисту, что вам редко нужно писать код, который пишет код.источник
__dict__
непосредственного использования объекта дайте объекту фактический объект словаря, либо через наследование, либо как атрибут.__setattr__
переопределение, что может привести к неожиданным результатам.setattr()
не имеет этой проблемыДругие пользователи указали, как ваш код может быть изменен, чтобы не зависеть от
eval
; Я предложу законный вариант использованияeval
, который встречается даже в CPython: тестирование .Вот один пример, который я нашел в том,
test_unary.py
где тест на то,(+|-|~)b'a'
поднимает лиTypeError
:Использование здесь явно не плохая практика; Вы определяете вход и просто наблюдаете за поведением.
eval
удобно для тестирования.Посмотрите на этот поиске для
eval
, исполненного на репозитории CPython; Тестирование с помощью eval активно используется.источник
Когда
eval()
используется для обработки предоставленного пользователем ввода, вы разрешаете пользователю Drop-to-REPL предоставлять что-то вроде этого:Вам это может сойти с рук, но обычно вам не нужны векторы для выполнения произвольного кода в ваших приложениях.
источник
В дополнение к @Nadia Alramli ответ, так как я новичок в Python , и хотел , чтобы проверить , как использование
eval
будет влиять на тайминги , я попробовал небольшую программу и ниже были наблюдения:источник