2016-01-23 2 views
3

Я гугле кучу и не могу показаться, чтобы выяснить, как на самом деле это сделать:Как использовать функции модуля в классах Python

Учитывая У меня есть универсальный метод утилиты как так:

def __square(n): 
    return n*n 

Тогда у меня есть некоторый класс, где я мог бы хотел использовать этот метод внутренне:

def __square(n): 
    return n*n 

class Foo: 
    def __init__(self): 
     self.baz = 2 

    def bar(self): 
     return self.baz + __square(self.baz) 

Ну, это не работает. Я получаю NameError '_Foo__square' is not defined

Почему?

В качестве обходного пути я в конечном итоге делает такие вещи, как это:

class Foo: 
    def __init__(self): 
     self.baz = 2 

    def bar(self): 
     return baz + self.square(self.baz) 

    def square(self,n): 
     return n*n 

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

Что такое «питонический» способ справиться с такими вещами?

EDIT

я понял, по крайней мере, одну часть этого: я получаю это поведение, потому что я думаю, что эти методы полезности, как частные, и я называть их как def __square(n):.

Я не осознавал, что это было особенным, и, набрав пример выше, я изначально не набирал его таким образом. Теперь я отредактировал вопрос, чтобы понять, как он был набран.

Итак, теперь мой вопрос: почему ставит __ перед методом верхнего уровня, сломайте его или, похоже,? Я понял, что это соглашение для обозначения «личных вещей» в Python, поскольку в этом случае он не работает, что бы вы рекомендовали вместо этого?

+0

Где находится 'square' в относительной структуре файлов? – kojiro

+0

Не удалось воспроизвести. Первые фрагменты работают так же хорошо для меня как в 2.7, так и в 3.5. –

+0

Я получаю это, когда у меня есть функции, определенные в одном файле, несколько строк. Использование Python 3.5 – Andrew

ответ

7

Вы не должны префикс своего имени функции двумя символами подчеркивания - __ - компилятор Python выполняет операцию манипулирования именами, когда имя, предваряемое двумя знаками подчеркивания, находится в коде внутри класса. - Прежде чем ваша ссылка на __square преобразуется в ссылку на несуществующий _Foo_square при компиляции (в байт-код).

Просто используйте один _, как в _square, и у вас не будет этой ошибки.

У Python нет таких вещей, как «частные» имена. По соглашению - и только соглашение - функция или атрибут с префиксом _ не должны вызываться или получать доступ из кода из других областей.

Некоторые из них пишут в Интернете, стремясь создать эквивалентность для любой концепции, существующей на других широко известных языках ООП, на самом деле упоминают, что префикс с двойным подчеркиванием эквивалентен «частным» переменным на этих языках. Это распространенная ошибка в старой документации - более поздние статьи избегают этой ошибки.

Поведение префикс двойного подчеркивания есть что-то другое - что иногда может служить той же цели, как private (в отличие от protected) атрибуты имеют: это преобразовать имя переменной в операции, известной как «имя коверкая» в течение Документация Python.Обычно это используется для имени атрибута и преобразуется в имя, уникальное для класса контейнера, таким образом, что оно будет доступно по умолчанию только для класса, который он был определен, а не для его подклассов. Преобразование является детерминированным и хорошо документированным: одно подчеркивание и имя класса добавляются к имени атрибута (в том числе два подчеркивания). Следовательно, класс Polygon, который имел бы атрибут __area, на самом деле имел бы _Polygon__area во время выполнения - и если производный класс class Square(Polygon): попытается получить доступ к атрибуту __area в своем коде, он фактически получит доступ к _Square__area во время выполнения. (Но можно было бы прочитать и написать суперкласс «__area», явно указав в коде код Square._Polygon__area)

+2

Сегодня я снова узнал что-то новое о python. Это описано здесь: https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references –

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