Pythonでselfを使用する方法

WBOY
リリース: 2023-05-17 22:40:48
転載
1930 人が閲覧しました

Python での self の使用法を紹介する前に、まず Python のクラスとインスタンスについて紹介しましょう
オブジェクト指向の最も重要な概念はクラスとインスタンスであることはわかっています。クラスは抽象テンプレートです。たとえば、抽象学生のようなものは Student クラスで表すことができます。インスタンスはクラスに基づいて作成された特定の「オブジェクト」であり、各オブジェクトはクラスから同じメソッドを継承しますが、そのデータは異なる場合があります。
1. Student クラスを例に挙げます。Python では、クラスは次のように定義されます:

class Student(object):
    pass
ログイン後にコピー

(Object) は、クラスがどのクラスから継承しているかを示します。Object クラスは、すべてのクラスが継承するクラスです。継承することになります。

2. インスタンス: クラスが定義された後、Student クラスを通じて Student のインスタンスを作成できます。インスタンスはクラス名 ():

student = Student()
ログイン後にコピー

3 を通じて作成されます。クラスはテンプレートとして機能するため、インスタンスを作成するときに、バインドする必要があると思われる属性を強制的に埋めることができます。ここでは Python の組み込みメソッドである __init__ メソッドが使用されています。たとえば、Student クラスでは、名前やスコアなどの属性をそれに結び付けます:

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
ログイン後にコピー

ここに注意してください: (1), __init__ メソッドの最初のパラメータは常に self であり、作成されたクラス インスタンス自体 を表します。 ## メソッドでは、それぞれを配置できます。self は作成されたインスタンス自体を指すため、このプロパティは self にバインドされます。 (2). __init__ メソッドでは、インスタンスを作成するときに空のパラメーターを渡すことはできません。__init__ メソッドに一致するパラメーターを渡す必要がありますが、self は必須ではありません。 Python インタープリターはインスタンス変数をそれ自体で渡します。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">&gt;&gt;&gt;student = Student(&quot;Hugh&quot;, 99) &gt;&gt;&gt;student.name &quot;Hugh&quot; &gt;&gt;&gt;student.score 99</pre><div class="contentsignin">ログイン後にコピー</div></div> さらに、ここで

self

はクラス自体を指します。self.name は ## です。 #Student クラスの属性変数は、Student クラスによって所有されます。 name は外部パラメータであり、Student クラスに付属するパラメータではありません。したがって、self.name = name は、外部パラメータ name の値を Student クラス独自の属性変数 self.name に割り当てることを意味します。 4. 通常の数値と比較すると、クラス内で関数を定義する場合の違いは 1 つだけです。つまり、最初のパラメーター

は常に

クラス自体のインスタンス変数であることです。 self であり、呼び出し時にこのパラメータを渡す必要はありません。また、クラスメソッド(関数)も通常の関数と何ら変わりはなく、デフォルトパラメータ、変数パラメータ、キーワードパラメータを使用することができます (*argsは可変パラメータ、args 受け取るのはタプルです**kw はキーワード パラメータであり、kw が受け取るものは dict)。 5. Student

クラス インスタンス自体がこれらのデータを所有しているため、これらのデータにアクセスするために外部関数からアクセスする必要はありませんが、Student 内でアクセスを直接定義できます。クラス。「データ」をカプセル化できるようにする、データの関数 (メソッド)。データをカプセル化するこれらの関数は Student クラス自体に関連付けられており、クラス メソッドと呼ばれます:

class Student(obiect):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def print_score(self):
        print "%s: %s" % (self.name, self.score)
ログイン後にコピー
>>>student = Student("Hugh", 99)
>>>student.print_score
Hugh: 99
ログイン後にコピー
このようにして、Student クラスを外側から見ると、何が必要かを知る必要があるだけです。インスタンスを作成するために指定された名前とスコア。印刷方法はすべて Student クラス内で定義されています。これらのデータとロジックはカプセル化されており、簡単に呼び出すことができますが、内部実装の詳細は不明です。

内部属性が外部からアクセスされないようにするには、属性名の前に 2 つのアンダースコア を追加します。Python では、インスタンスの変数名が ## で始まる場合、 #, 内部からのみアクセスでき、外部からはアクセスできないプライベート変数 (private) になっているため、Student クラスを変更しました:

class Student(object):

    def __init__(self, name, score):
        self.__name = name
        self.__score = score
    def print_score(self):
        print "%s: %s" %(self.__name,self.__score)
ログイン後にコピー

変更後、外部コードには変更はありません。ただし、インスタンス変数 .__name とインスタンス変数

.__score

には外部からアクセスできなくなります: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">&gt;&gt;&gt; student = Student(&amp;#39;Hugh&amp;#39;, 99) &gt;&gt;&gt; student.__name Traceback (most recent call last): File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt; AttributeError: &amp;#39;Student&amp;#39; object has no attribute &amp;#39;__name&amp;#39;</pre><div class="contentsignin">ログイン後にコピー</div></div> これにより、外部コードが内部状態を変更できないことが保証されます。オブジェクトを自由に操作できるため、アクセス制限の保護を通じてコードがより堅牢になります。 しかし、外部コードが名前とスコアを取得したい場合はどうなるでしょうか? get_name や get_score などのメソッドを Student クラスに追加できます。

class Student(object):
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score
ログイン後にコピー

外部コードによるスコアの変更を許可したい場合はどうすればよいでしょうか? set_score メソッドを Student クラスに追加できます。

class Student(object):
    ...

    def set_score(self, score):
        self.__score = score
ログイン後にコピー

Python では、変数名は

__xxx__

に似ていることに注意してください。つまり、変数名は 2 つのアンダースコアで始まり、最後に続きます。特殊な変数です。特殊な変数はプライベート変数ではなく、直接アクセスできます。したがって、

__name__

__score__ などの変数名は使用できません。 _name など、アンダースコアで始まるインスタンス変数名が表示されることがあります。このようなインスタンス変数には外部からアクセスできます。ただし、規則によれば、このような変数が表示されるときは、「」を意味します。アクセスは可能ですが、プライベート変数として扱い、勝手にアクセスしないでください。」

カプセル化のもう 1 つの利点は、次のような新しいメソッド

を Student クラスにいつでも追加できることです。 ,

get_grade

メソッドは、内部実装の詳細を知らなくても、インスタンス変数に対して直接呼び出すことができます:

>>> student.get_grade()
&#39;A&#39;
ログイン後にコピー

6、self的仔细用法
(1)、self代表类的实例,而非类。

class Test:
    def ppr(self):
        print(self)
        print(self.__class__)

t = Test()
t.ppr()
执行结果:
<__main__.Test object at 0x000000000284E080>
<class &#39;__main__.Test&#39;>
ログイン後にコピー

从上面的例子中可以很明显的看出,self代表的是类的实例。而self.__class__则指向类。
注意:把self换成this,结果也一样,但Python中最好用约定俗成的self。
(2)、self可以不写吗?
在Python解释器的内部,当我们调用t.ppr()时,实际上Python解释成Test.ppr(t),也就是把self替换成了类的实例。

class Test:
    def ppr():
        print(self)

t = Test()
t.ppr()
ログイン後にコピー

运行结果如下:

Traceback (most recent call last):
File "cl.py", line 6, in
t.ppr()
TypeError: ppr() takes 0 positional arguments but 1 was given

运行时提醒错误如下:ppr在定义时没有参数,但是我们运行时强行传了一个参数。

由于上面解释过了t.ppr()等同于Test.ppr(t),所以程序提醒我们多传了一个参数t。

这里实际上已经部分说明了self在定义时不可以省略。

当然,如果我们的定义和调用时均不传类实例是可以的,这就是类方法。

class Test:
    def ppr():
        print(__class__)

Test.ppr()

运行结果:
<class &#39;__main__.Test&#39;>
ログイン後にコピー

(3)、在继承时,传入的是哪个实例,就是那个传入的实例,而不是指定义了self的类的实例。

class Parent:
    def pprt(self):
        print(self)

class Child(Parent):
    def cprt(self):
        print(self)
c = Child()
c.cprt()
c.pprt()
p = Parent()
p.pprt()
ログイン後にコピー

运行结果:

<__main__.Child object at 0x0000000002A47080>
<__main__.Child object at 0x0000000002A47080>
<__main__.Parent object at 0x0000000002A47240>

解释:
运行c.cprt()时应该没有理解问题,指的是Child类的实例。
但是在运行c.pprt()时,等同于Child.pprt(c),所以self指的依然是Child类的实例,由于self中没有定义pprt()方法,所以沿着继承树往上找,发现在父类Parent中定义了pprt()方法,所以就会成功调用。

(4)、在描述符类中,self指的是描述符类的实例

class Desc:
    def __get__(self, ins, cls):
        print(&#39;self in Desc: %s &#39; % self )
        print(self, ins, cls)
class Test:
    x = Desc()
    def prt(self):
        print(&#39;self in Test: %s&#39; % self)
t = Test()
t.prt()
t.x
ログイン後にコピー

运行结果如下:

self in Test: <__main__.Test object at 0x0000000002A570B8>
self in Desc: <__main__.Desc object at 0x000000000283E208>
<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8>

这里主要的疑问应该在:Desc类中定义的self不是应该是调用它的实例t吗?怎么变成了Desc类的实例了呢?
因为这里调用的是t.x,也就是说是Test类的实例t的属性x,由于实例t中并没有定义属性x,所以找到了类属性x,而该属性是描述符属性,为Desc类的实例而已,所以此处并没有顶用Test的任何方法。

那么我们如果直接通过类来调用属性x也可以得到相同的结果。

下面是把t.x改为Test.x运行的结果。

self in Test: <__main__.Test object at 0x00000000022570B8>
self in Desc: <__main__.Desc object at 0x000000000223E208>
<__main__.Desc object at 0x000000000223E208> None <class &#39;__main__.Test&#39;>
ログイン後にコピー

以上がPythonでselfを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!