ホームページ  >  記事  >  バックエンド開発  >  Python オブジェクト指向プログラミングに関する知識ポイントのまとめ

Python オブジェクト指向プログラミングに関する知識ポイントのまとめ

高洛峰
高洛峰オリジナル
2017-02-18 10:14:221355ブラウズ

Python は最初からオブジェクト指向言語であり、そのため Python でクラスやオブジェクトを作成するのは簡単です。 Pythonのオブジェクト指向プログラミングについては以下の記事で詳しく紹介していますので、ぜひ参考にしてみてください。

まえがき

これまでオブジェクト指向プログラミング言語に触れたことがない場合は、まずオブジェクト指向言語のいくつかの基本的な機能を理解し、頭の中でオブジェクト指向の基本的な概念を形成する必要があるかもしれません。 Python でオブジェクト指向プログラミングを簡単に学習できます。

次に、Python オブジェクト指向プログラミングについて学びましょう。

クラスとインスタンス

クラスはオブジェクトの定義であり、インスタンスはクラスで定義されたオブジェクトの固有の情報を格納する「実際のオブジェクト」です。

クラス、属性、メソッドの命名規則

クラス名は通常、大文字で始まります。これは標準的な規則であり、特にインスタンス化中 (関数呼び出しのように見える場合もあります) にクラスを識別するのに役立ちます。また、データ属性 (変数または定数) はデータ値の名前のように聞こえ、メソッド名は対応するオブジェクトまたは値の動作を示す必要があります。

もう 1 つの表現方法は、データ値は名前として名詞を使用し、メソッドは述語 (動詞とオブジェクト) を使用する必要があります。データ項目は操作対象のオブジェクトであり、メソッドはプログラマがオブジェクトに対してどのような操作を実行したいかを示す必要があります。

定義されたクラスでは、大まかにこのガイドラインに従い、データ値は「name」、「phone」、「email」のようになり、動作は「updatePhone」、「updateEmail」のようになります。これは、「mixedCase」または「camelCase」と呼ばれることがよくあります。 Python 仕様では、「update_phone」、「update_email」など、アンダースコアを含むラクダ表記を使用することが推奨されています。クラスの名前も慎重に付ける必要があります。「AddrBookEntry」、「RepairShop」などの名前が適切です。

class AddrBookEntry(object):

 def __init__(self, name, phone, email):
 self.name = name
 self.phone = phone
 self.email = email

 def update_phone(self, phone):
 self.phone = phone

 def update_email(self. email):
 self.email = email

新しいスタイルのクラスと古いスタイルのクラス

新しいスタイルのクラスと従来のクラス宣言の最大の違いは、すべての新しいスタイルのクラスが少なくとも 1 つの親クラスを継承する必要があることです。継承するクラスがない場合は、オブジェクトクラスを継承できます。オブジェクトは「すべてのクラスの母」であり、すべてのクラス継承構造の最上位に位置します。オブジェクトの直接的または間接的なサブクラス化がない場合は、クラシック クラスが定義されます。つまり、親クラスが指定されていない場合、またはサブクラス化される基本クラスに親クラスがない場合は、クラシック クラスが作成されます。

Python3 で定義されたクラスは、デフォルトでは新しいスタイルのクラスです。Python2 で新しいスタイルのクラスを定義するには、オブジェクトを継承するか、新しいスタイルのクラスを継承する必要があります。

self 変数

クラスのメソッドには、通常の関数との特別な違いが 1 つだけあります。つまり、追加の最初のパラメーター名が必要ですが、このメソッドを呼び出すときにこのパラメーターに値を割り当てる必要はありません。Pythonこの値を提供します。この特定の変数はオブジェクト自体を参照し、慣例によりその名前は self です。このパラメータには任意の名前を付けることができますが、self という名前を使用することを強くお勧めします。他の名前は非推奨です。

__init__() メソッド

__init__() はクラス コンストラクターに似ていますが、実際にはコンストラクターではありません。 Python はインスタンスを作成した後、インスタンス化プロセス中に __init__() メソッドを呼び出します。これは主に、初期値の設定や予備的な診断コードの実行などの追加の動作を定義できます。インスタンスが作成されると、インスタンス化呼び出しによって、インスタンスに戻る前に特定のタスクまたは設定が実行されます。

バインドされたメソッドとアンバインドされたメソッド

Python では、クラスにアクセスするメソッドには、インスタンスを通じて直接アクセスすることも、クラスを通じて直接アクセスすることもできます。ただし、Python では、インスタンスなしではメソッドを呼び出すことができないことが厳密に要求されます。この制限は Python でバインディングと呼ばれるもので、メソッドを直接呼び出すにはメソッドを (インスタンスに) バインドする必要があります。非バインド メソッドを呼び出すこともできますが、呼び出しが成功することを保証するには、インスタンス オブジェクトを明示的に指定する必要があります。ただし、バインドされているかどうかに関係なく、メソッドは、ほとんどの場合インスタンスを通じて呼び出されますが、メソッドが存在するクラスの固有のプロパティです。 Python のクラス メソッドもオブジェクトです。クラスを介して直接アクセスされるメソッドは「非バインド メソッド」と呼ばれ、インスタンスを介してアクセスされるメソッドは「バインド メソッド」と呼ばれることは簡単に理解できます。バインドされていないメソッド オブジェクト。これを呼び出すには、最初の引数としてインスタンスを明示的に指定する必要があります。

2. バインドされたインスタンス メソッド: インスタンス アクセス メソッドを通じてバインドされたメソッド オブジェクトを返す self

があります。 Python はインスタンスをメソッドに自動的にバインドするため、呼び出し時にインスタンス パラメーターを渡す必要はありません。

例:

class Test:
 def func(self, message):
 print message

object1 = Test()
x = object1.func
x("绑定方法对象,实例是隐藏的")

t = Test.func
t(object1, "未绑定方法对象,需要传递一个实例")
# t("未绑定方法对象,需要传递一个实例") # 错误的调用

クラス属性とインスタンス属性

类属性仅是与类相关的数据值,和实例属性不同,类属性和实例无关。这些值像静态成员那样被引用,即使在多次实例化中调用类,它们的值都保持不变。不管如何,静态成员不会因为实例而改变它们的值,除非实例中显式改变它们的值。 实例属性与类属性的比较,类似于自动变量和静态变量,但这只是笼统的类推。在你对自动变量和静态变量还不是很熟的情况下,不要深究这些。

类和实例都是名字空间。类是类属性的名字空间,实例则是实例属性的。

可采用类来访问类属性,如果实例没有同名的属性的话,也可以用实例来访问。

私有化

Python并不直接支持私有方式,而要靠程序员自己把握在外部进行特性修改的时机。

为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可。由双下划线 __ 开始的属性在运行时被“混淆”,所以直接访问是不允许的。

实际上,在 Python 带有双下划线的属性或方法并非正真意义上的私有,它们仍然可以被访问。在类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式:

>>> class TestObj(object):
... __war = "world"
... 
... def __init__(self):
...  self.__har = "hello"
...  
... def __foo(self):
...  print(self.__har + self.__war)
...  
... 
... 
>>> t = TestObj()
>>> dir(t)
['_TestObj__foo', '_TestObj__har', '_TestObj__war', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getat
tribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__
', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> t.__war
Traceback (most recent call last):
 File "<input>", line 1, in <module>
 t.__war
AttributeError: 'TestObj' object has no attribute '__war'
>>> t.__har
Traceback (most recent call last):
 File "<input>", line 1, in <module>
 t.__har
AttributeError: 'TestObj' object has no attribute '__har'
>>> t.foo()
Traceback (most recent call last):
 File "<input>", line 1, in <module>
 t.foo()
AttributeError: 'TestObj' object has no attribute 'foo'
>>> t._TestObj__war
'world'
>>> t._TestObj__har
'hello'
>>> t._TestObj__foo()
helloworld

__slots__ 类属性

正常情况下,当我们定义了一个 class,创建了一个 class 的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。在 Python 中默认用字典来存储实例的属性。

示例:

>>> class A():
... pass
... 
>>> a = A()
>>> a.name = "huoty"
>>> a.age = 25
>>> print a.name
huoty
>>> print a.age
25
>>> a.__dict__
{'age': 25, 'name': 'huoty'}

字典位于实例的“心脏” 。 __dict__属性跟踪所有实例属性。举例来说,你有一个实例 inst,它有一个属性 foo,那使用 inst.foo 来访问它与使用 inst.__dict__['foo'] 来访问是一致的。

字典会占据大量内存,如果你有一个属性数量很少的类,但有很多实例,那么正好是这种情况。为内存上的考虑,可以使用 __slots__ 属性来替代 __dict__ 。

, __slots__ 是新式类的特性。基本上, __slots__ 是一个类变量,由一序列对象组成,由所有合法标识构成的实例属性的集合来表示。它可以是一个列表,元组或可迭代对象。也可以是标识实例能拥有的唯一的属性的简单字符串。任何试图创建一个其名不在 __slots__ 中的名字的实例属性都将导致 AttributeError 异常:

>>> class SlotedClass(object):
... __slots__ = ("foo", "bar")
... 
... 
>>> c = SlotedClass()
>>> c.foo = 42
>>> c.bar = "hello"
>>> c.goo = "don't think so"
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'SlotedClass' object has no attribute 'goo'

这种特性的主要目的是节约内存。其副作用是某种类型的"安全",它能防止用户随心所欲的动态增加实例属性。带 __slots__ 属性的类定义不会存在 __dict__ 了(除非你在 __slots__ 中增加 __dict__ 元素)。


更多关于Python面向对象编程的知识点总结相关文章请关注PHP中文网!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。