2015-04-22 3 views
1

Что может пойти не так, если я непреднамеренно перезаписываю/маскирует встроенную функцию в Python?Переписывание встроенной функции в Python

Могу ли я испытать что-нибудь хуже, чем очевидная ошибка доступа к локальной функции вместо встроенной функции?

Например:

def max(a, b): 
    pass 

class MyCompileTool(object): 
    def __init__(self, id): 
     self.id = id 

    def compile(self): 
     min = "3.4.4" 
     ... 

Даже в некоторых официальных модулей: argparse.add_argument(..., type, ...)

+0

Существует много возможных сценариев, основанных на факте, что кто-то/вы не будете теперь/забывать об этом и попытаетесь назвать эти функции. Эти вопросы кажутся слишком широкими. Кроме того, обратите внимание, что в вашем примере вы не изменяете встроенные модули, просто создавайте локальные переменные, которые затеняют встроенные модули только в рамках метода 'compile'. – BartoszKP

+0

Разве это не очевидно ?! Вы можете случайно вызвать неправильную функцию и либо получить ошибку, либо (что еще хуже) получить неверный результат. Обратите внимание, что ** переписывание ** встроенных модулей (намеренно) очень сложно сделать случайно, это ** затенение ** их, что вам нужно следить. Такие инструменты, как 'pylint', предупредит вас об этом. Также избегайте импорта подстановочных знаков ('from foo import *') по той же причине. – jonrsharpe

+2

Я чувствую, что OP действительно спрашивает: «Помимо очевидной ошибки, когда вы больше не можете получить доступ к этой функции, есть ли какие-либо последствия, такие как« внутренние функции Python, которые используют «max», будут запутаны и сбой, когда они смогут », t найти обычную реализацию?? ". На что ответ, IIRC, «нет». – Kevin

ответ

3

Вы не перезаписать встроенный min здесь, вы просто создать min местный, который будет предпочтительным, если последующий код compile будет содержат обращения к min:

class MyCompileTool(object): 
    ... 

    def compile(self): 
     min = "3.4.4" 
     x = min(1, 2) 
     # ^^^ "3.4.4".__call__(1, 2) 
     # This will throw exception because strings doesn't have __call__ 
x = min(3, 4) 
# ^^^ __builtins__.min 

К shad вл min в целом модуль, сделать это в глобальном пространстве имен:

min = "3.4.4" 
# Now all calls of min will go to that string 

class MyCompileTool(object): 
    pass 

Для получения дополнительной информации о том, как имена разрешаются в Python, проверьте документацию: 4.1. Naming and binding

+0

О слове «* полностью *»: Не будет ли вызов в 'min()' в импортированном модуле по-прежнему ссылаться на регулярный 'min()'? Я не слишком уверен, как эти правила работают ... –

+0

@ HannesOvrén, спасибо за это внимание, вы абсолютно правы - это делается в глобальном пространстве имен одного модуля. У меня есть мой ответ. – myaut

+0

@myaut "single module", если только другой модуль не выполнит 'from x import *'. – BartoszKP

0

В этой конкретной ситуации, то, вероятно, не так много, что может/пойдет не так. Вы просто затеняете min с локальной переменной в своем методе, поэтому вы, вероятно, не нанесете большого урона. В общем, хотя, вы могли бы увидеть что-то вроде этого:

>>> min = "3.4.4" 
>>> x = min(3, 4, 5) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'str' object is not callable 
>>> 

Это может сбить вас с толку или (еще хуже) это может сбить с толку человека, который должен идти и поддерживать ваш код позже. Было бы еще хуже, если бы вы сделали это по всему миру, например:

min = "3.4.4" 

def main(): 
    x = min(3, 4, 5) 

В целом, это плохая практика. Не делай этого.

Смежные вопросы