Как избежать явного "я" в Python?

Я изучаю Python, следуя инструкциям pygame.

В этой связи я нашел широкое использование ключевого слова self и, исходя из основного фона Java, обнаружил, что я забываю вводить себя. Например, вместо self.rect.centerx я бы набрал rect.centerx, потому что для меня rect уже является переменной-членом класса.

Параллель Java, о которой я могу думать, для этой ситуации - это префикс всех ссылок на переменные-члены с этим.

Я застрял, префиксные все переменные-члены, или есть способ объявить их, что позволит мне избежать этого?

Даже если то, что я предлагаю, не является питоническим, мне все равно хотелось бы узнать, возможно ли это.

Я рассмотрел эти связанные вопросы SO, но они не совсем отвечают на то, что я хочу:

Ответ 1

Python требует указать self. В результате никогда не возникает путаницы в отношении того, что участник, а что нет, даже без полного определения класса. Это приводит к полезным свойствам, таким как: вы не можете добавлять членов, которые случайно затеняют нечлены и тем самым нарушают код.

Один экстремальный пример: вы можете написать класс без каких-либо знаний о том, какие базовые классы он может иметь, и всегда знать, обращаетесь ли вы к члену или нет:

class A(some_function()):
  def f(self):
    self.member = 42
    self.method()

Что полный код! (some_function возвращает тип, используемый в качестве базы.)

Другое, где методы класса динамически составлены:

class B(object):
  pass

print B()
# <__main__.B object at 0xb7e4082c>

def B_init(self):
  self.answer = 42
def B_str(self):
  return "<The answer is %s.>" % self.answer
# notice these functions require no knowledge of the actual class
# how hard are they to read and realize that "members" are used?

B.__init__ = B_init
B.__str__ = B_str

print B()
# <The answer is 42.>

Помните, что оба этих примера экстремальны, и вы не увидите их каждый день, и я не предлагаю вам часто писать такой код, но они явно показывают, что явные потребности явным образом требуются.

Ответ 2

Фактически self не является ключевым словом, это просто имя, условно заданное первому параметру методов экземпляра в Python. И этот первый параметр не может быть пропущен, так как это единственный механизм, который метод знает о том, какой экземпляр вашего класса он вызывает.

Ответ 3

Вы можете использовать любое имя, которое вы хотите, например

class test(object):
    def function(this, variable):
        this.variable = variable

или даже

class test(object):
    def function(s, variable):
        s.variable = variable

но вы застряли в использовании имени для области.

Я не рекомендую использовать что-то другое для себя, если у вас нет убедительной причины, поскольку это сделало бы его чуждым для опытных питонистов.

Ответ 4

Предыдущие ответы - это в основном варианты "ты не можешь" или "ты не должен". Хотя я согласен с последним мнением, вопрос технически до сих пор остается без ответа.

Кроме того, есть законные причины, по которым кто-то может захотеть сделать что-то в соответствии с тем, что задает реальный вопрос. Иногда я сталкиваюсь с длинными математическими уравнениями, в которых использование длинных имен делает уравнение неузнаваемым. Вот несколько способов, как вы могли бы сделать это в стандартном примере:

import numpy as np
class MyFunkyGaussian() :
    def __init__(self, A, x0, w, s, y0) :
        self.A = float(A)
        self.x0 = x0
        self.w = w
        self.y0 = y0
        self.s = s

    # The correct way, but subjectively less readable to some (like me) 
    def calc1(self, x) :
        return (self.A/(self.w*np.sqrt(np.pi))/(1+self.s*self.w**2/2)
                * np.exp( -(x-self.x0)**2/self.w**2)
                * (1+self.s*(x-self.x0)**2) + self.y0 )

    # The correct way if you really don't want to use 'self' in the calculations
    def calc2(self, x) :
        # Explicity copy variables
        A, x0, w, y0, s = self.A, self.x0, self.w, self.y0, self.s
        sqrt, exp, pi = np.sqrt, np.exp, np.pi
        return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
                * exp( -(x-x0)**2/w**2 )
                * (1+s*(x-x0)**2) + y0 )

    # Probably a bad idea...
    def calc3(self, x) :
        # Automatically copy every class vairable
        for k in self.__dict__ : exec(k+'= self.'+k)
        sqrt, exp, pi = np.sqrt, np.exp, np.pi
        return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
                * exp( -(x-x0)**2/w**2 )
                * (1+s*(x-x0)**2) + y0 )

g = MyFunkyGaussian(2.0, 1.5, 3.0, 5.0, 0.0)
print(g.calc1(0.5))
print(g.calc2(0.5))
print(g.calc3(0.5))

Третий пример - то есть использование for k in self.__dict__ : exec(k+'= self.'+k) - это в основном то, о чем на самом деле просит вопрос, но позвольте мне прояснить, что я не думаю, что это вообще хорошая идея.

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

Ответ 5

да, вы всегда должны указывать self, потому что явное лучше, чем неявное, согласно философии python.

Вы также узнаете, что способ программирования в python сильно отличается от того, как вы программируете в java, поэтому использование self имеет тенденцию к снижению, потому что вы не проецируете все внутри объекта. Скорее, вы больше используете функцию уровня модуля, которая может быть лучше протестирована.

Кстати,

. Сначала я ненавидел его, теперь я ненавижу обратное. то же для управления потоком с отступом.

Ответ 6

self является частью синтаксиса python для доступа к элементам объектов, поэтому я боюсь, что вы застряли с ним

Ответ 7

"Я" является обычным заполнителем текущего экземпляра объекта класса. Его используют, когда вы хотите ссылаться на свойство объекта или поле или метод внутри класса, как будто вы имеете в виду "себя". Но чтобы сделать его короче, кто-то в области программирования Python начал использовать "я" , другие сферы используют "this", но они делают его ключевым словом, которое нельзя заменить. Я скорее использовал "его" для повышения удобочитаемости кода. Его одна из хороших вещей в Python - у вас есть свобода выбора своего собственного заполнителя для экземпляра объекта, кроме "я" . Пример для self:

class UserAccount():    
    def __init__(self, user_type, username, password):
        self.user_type = user_type
        self.username = username            
        self.password = encrypt(password)        

    def get_password(self):
        return decrypt(self.password)

    def set_password(self, password):
        self.password = encrypt(password)

Теперь мы заменяем "я" на "его":

class UserAccount():    
    def __init__(its, user_type, username, password):
        its.user_type = user_type
        its.username = username            
        its.password = encrypt(password)        

    def get_password(its):
        return decrypt(its.password)

    def set_password(its, password):
        its.password = encrypt(password)

который теперь более читаем?

Ответ 8

Да, самость утомительна. Но, лучше?

class Test:

    def __init__(_):
        _.test = 'test'

    def run(_):
        print _.test

Ответ 9

На самом деле вы можете использовать рецепт "Неявное Я" из презентации Армина Ронахера "5 лет плохих идей" (Google google it).

Это очень умный рецепт, как и почти все от Армина Ронахера, но я не думаю, что эта идея очень привлекательна. Я думаю, что предпочел бы явное это в С#/Java.

Обновить. Ссылка на "рецепт плохой идеи": https://speakerdeck.com/mitsuhiko/5-years-of-bad-ideas?slide=58

Ответ 10

От: Self Hell - больше функций с сохранением состояния.

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