web-dev-qa-db-ja.com

Pythonで明示的な「自己」を避ける方法は?

私はいくつかの pygameチュートリアル に従って、Pythonを学習しています。

その中で、キーワードselfの広範な使用を発見し、主にJavaバックグラウンドから来て、私はselfと入力するのを忘れます。たとえば、self.rect.centerxと入力しますrect.centerx、私にとって、rectはすでにクラスのメンバー変数であるためです。

Javaパラレル)この状況では、メンバー変数へのすべての参照の前にthisを付ける必要があると考えることができます。

すべてのメンバー変数にselfの接頭辞を付けたままにしますか、それともそうしないで済むように宣言する方法はありますか?

私が提案しているのはPythonicでなくても、それが可能かどうか知りたいです。

私はこれらの関連するSOの質問を見てきましたが、私が何を求めているのか全く答えていません:

110
bguiz

Pythonではselfを指定する必要があります。結果は、完全なクラス定義が表示されていなくても、メンバーであるものとそうでないものを混同することはありません。これにより、次のような便利なプロパティが得られます。非メンバーを誤ってシャドウしてメンバーを追加することはできず、コードが破損します。

極端な例:クラスの基本クラスを知らなくてもクラスを記述でき、メンバーにアクセスしているかどうかを常に把握できます。

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

それがcompleteコードです! (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.>

これらの例はどちらも極端であり、毎日表示されることはありません。また、このようなコードを頻繁に記述することをお勧めしませんが、明示的に必要な自己の側面を明確に示します。

88
Roger Pate

実際、selfはキーワードではなく、Pythonのインスタンスメソッドの最初のパラメーターに従来から与えられている名前にすぎません。そして、この最初のパラメーターは、クラスのどのインスタンスが呼び出されているかを知るための唯一のメカニズムであるため、スキップすることはできません。

24
Michał Marczyk

以前の回答はすべて、基本的に「できない」または「すべきではない」の変形です。私は後者の感情に同意しますが、質問は技術的に未回答のままです。

さらに、実際の質問が求めていることに沿って誰かが何かをしたいと思う正当な理由があります。私がときどき遭遇することの1つは、長い名前の数式を使用すると数式が認識できなくなる長い数式です。缶詰の例でこれを行う方法は次のとおりです。

_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))
_

3番目の例-for k in self.__dict__ : exec(k+'= self.'+k)を使用することは、基本的に質問が実際に求めていることですが、一般的には良い考えではないと思います。

詳細情報、およびクラス変数、さらには関数を反復処理する方法については、 この質問 の回答と説明を参照してください。動的に変数に名前を付ける他の方法と、これが通常良いアイデアではない理由については、 このブログ投稿 を参照してください。

21
argentum2f

好きな名前を使用できます、例えば

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

あるいは

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

しかし、スコープの名前を使用することに固執しています。

あなたが説得力のある理由がない限り、自己とは異なるものを使用することはお勧めしません。

21
Esteban Küber

はい、python哲学によると、明示的は暗黙的よりも優れているため、常にselfを指定する必要があります。

また、pythonでプログラミングする方法は、Javaでプログラミングする方法とは非常に異なるため、selfの使用は、すべてを内部に投影しないため減少する傾向があることもわかります。オブジェクト。むしろ、よりよくテストできるモジュールレベルの関数をより多く使用します。

ところで。最初は嫌いだったが、今は反対が嫌いだ。インデント駆動のフロー制御でも同じです。

9
Stefano Borini

selfは、オブジェクトのメンバーにアクセスするためのpython構文の一部です。

5
Charles Ma

「自己」は、クラスの現在のオブジェクトインスタンスの従来のプレースホルダーです。クラス内のオブジェクトのプロパティ、フィールド、またはメソッドを、「自分」を参照しているように参照する場合に使用します。しかし、Pythonプログラミングレルムで "self"を使用し始めた人を短くするために、他のレルムは "this"を使用しますが、置換できないキーワードとして使用します。 「コードの読みやすさを向上させます。Python-の良い点の1つ-「self」以外のオブジェクトのインスタンスの独自のプレースホルダーを自由に選択できます。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)

ここで、「self」を「its」に置き換えます。

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)

どちらがより読みやすくなりましたか?

5
LEMUEL ADANE

実際、Armin Ronacherのプレゼンテーション「5年間の悪いアイデア」のレシピ「Implicit self」を使用できます(グーグルit)。

Armin Ronacherのほぼすべてのものと同様、非常に賢いレシピですが、このアイデアは非常に魅力的ではないと思います。 C#/ Javaで明示的なthisを好むと思います。

更新。 「悪い考えのレシピ」へのリンク: https://speakerdeck.com/mitsuhiko/5-years-of-bad-ideas?slide=58

1
Alex Yu

ええ、自己は退屈です。しかし、それは良いですか?

class Test:

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

    def run(_):
        print _.test
1
user804830

From: Self Hell-よりステートフルな関数。

...ハイブリッドアプローチが最適です。実際に計算を行うすべてのクラスメソッドをクロージャに移動し、構文をクリーンアップするための拡張機能をクラスに保持する必要があります。クロージャーをクラスに詰め込み、クラスをネームスペースのように扱います。クロージャーは本質的に静的な関数であるため、クラス内であってもselfs *を必要としません...

0
user5554473