序文
Python は最初からオブジェクト指向言語であるため、Python でクラスやオブジェクトを作成するのは簡単です。この章では、Python によるオブジェクト指向プログラミングについて詳しく紹介します。
これまでにオブジェクト指向プログラミング言語に触れたことがない場合は、まずオブジェクト指向言語のいくつかの基本的な機能を理解し、頭の中でオブジェクト指向の基本的な概念を形成する必要があるかもしれません。これは Python の学習に役立ちます。オブジェクト指向プログラミング。
次に、オブジェクト指向の基本的な特徴を簡単に理解しましょう。
オブジェクト指向テクノロジーの概要
- クラス: 同じプロパティとメソッドを持つオブジェクトのコレクションを記述するために使用されます。コレクション内のすべてのオブジェクトに共通のプロパティとメソッドを定義します。オブジェクトはクラスのインスタンスです。
- メソッド: クラス内で定義された関数。
- クラス変数: クラス変数は、インスタンス化されたオブジェクト全体でパブリックです。クラス変数は、クラス内および関数本体の外で定義されます。クラス変数は通常、インスタンス変数としては使用されません。
- データ メンバー: クラス変数またはインスタンス変数は、クラスとそのインスタンス オブジェクトに関連するデータを処理するために使用されます。
- メソッドの書き換え: 親クラスから継承したメソッドがサブクラスのニーズを満たせない場合は、メソッドを書き換えることができます。このプロセスはメソッド オーバーライドと呼ばれ、メソッドの書き換えとも呼ばれます。
- ローカル変数: メソッド内で定義された変数は、現在のインスタンスのクラスにのみ影響します。
- インスタンス変数: クラスの宣言において、属性を変数で表現したものをインスタンス変数と呼びます。インスタンス変数とは、自分自身を修飾した変数のことです。
- 継承: 派生クラスは、基本クラスのフィールドとメソッドを継承します。継承により、派生クラスのオブジェクトを基本クラス オブジェクトとして扱うこともできます。たとえば、次のような設計があります。Dog タイプのオブジェクトは、「is-a」関係 (たとえば、Dog is an Animal) をシミュレートする Animal クラスから派生します。
- インスタンス化: クラスのインスタンス、クラスの特定のオブジェクトを作成します。
- オブジェクト: クラスによって定義されたデータ構造のインスタンス。オブジェクトには 2 つのデータ メンバー (クラス変数とインスタンス変数) とメソッドが含まれます。
他のプログラミング言語と比較して、Python は新しい構文やセマンティクスをできるだけ追加せずにクラスのメカニズムを追加します。
Python のクラスは、オブジェクト指向プログラミングのすべての基本機能を提供します。クラスの継承メカニズムにより複数の基本クラスが許可され、派生クラスは基本クラスのメソッドをオーバーライドでき、基本クラス内の同じ名前のメソッドを呼び出すことができます。
オブジェクトには、任意の量および種類のデータを含めることができます。
クラス定義
構文形式は次のとおりです。
class ClassName:
<statement-1>
.
.
.
<statement-N>
クラスがインスタンス化されると、そのプロパティを使用できるようになり、実際、クラスの作成後は、クラス名を介してそのプロパティにアクセスできるようになります。
コード例:
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
物体
オブジェクトは、プロパティ参照とインスタンス化という 2 つの操作をサポートします。
プロパティ参照は、Python のすべてのプロパティ参照と同じ標準構文 obj.name を使用します。
クラス オブジェクトが作成された後は、クラス名前空間内のすべての名前が有効な属性名になります。したがって、クラス定義が次のようになったとします。
#!/usr/bin/python3
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
上記は新しいクラス インスタンスを作成し、そのオブジェクトを空のオブジェクトであるローカル変数 x に割り当てます。
上記のプログラムを実行した出力結果は次のようになります。
MyClass クラスの属性 i は次のとおりです: 12345
MyClass クラスのメソッド f の出力は次のとおりです: hello world
クラスには_ init _() と呼ばれる特別なメソッド ( constructor ) があり、次のようにクラスがインスタンス化されるときに自動的に呼び出されます。
def __init__(self):
self.data = []
このクラスは _ init _() メソッドを定義しており、クラスのインスタンス化操作により _ init _() メソッドが自動的に呼び出されます。クラスMyClassが次のようにインスタンス化されると、対応する _ init _() メソッドが呼び出されます。
x = MyClass()
もちろん、_ init _() メソッドにはパラメーターを含めることができ、パラメーターはinit () を通じてクラスのインスタンス化操作に渡されます。例えば:
#!/usr/bin/python3
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
self はクラスのインスタンスを表し、非
クラスメソッドには通常の関数との特別な違いが 1 つだけあります。追加の最初のパラメータ名が必要です。慣例により、これはselfです。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
上記の例の実行結果は次のようになります。
<_ main _.Test オブジェクト (0x000001B55C75B610)>
<クラス '_ main _.Test'>
実行結果から、self がクラスのインスタンスと現在のオブジェクトのアドレスを表し、self.class がクラスを指していることがわかります。
self は Python のキーワードではないので、runoob に置き換えると通常通り実行できます。
class Test:
def prt(tarzan):
print(tarzan)
print(tarzan.__class__)
t = Test()
t.prt()
上記の例の実行結果は次のようになります。
<_ main _.Test オブジェクト (0x000001702A38B650)>
<クラス '_ main _.Test'>
クラスメソッド
クラス内では、defキーワードを使用してメソッドを定義します。一般的な関数定義とは異なり、クラス メソッドには最初のパラメータであるパラメータselfが含まれている必要があります。Selfはクラスのインスタンスを表します。
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁,体重 %d 公斤。" %(self.name,self.age,self.__weight))
# 实例化类
p = people('tarzan',30,70)
p.speak()
上記のプログラムを実行した出力結果は次のようになります。
ターザンは言った:私は30歳で、体重は70kgです
継承する
Python はクラスの継承もサポートしていますが、言語が継承をサポートしていない場合、クラスは意味がありません。派生クラスの定義は次のとおりです。
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
サブクラス (DerivedClassName) は、親クラス (BaseClassName) のプロパティとメソッドを継承します。
BaseClassName (インスタンス内の基本クラス名) は、派生クラスと同じスコープで定義する必要があります。クラスに加えて、式を使用することもできます。これは、基本クラスが別のモジュールで定義されている場合に便利です。
class DerivedClassName(modname.BaseClassName):
コード例
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()
上記のプログラムを実行した出力結果は次のようになります。
ケンは言いました:私は10歳で小学3年生です
多重継承
Python では、複数の継承形式のサポートも限定的です。多重継承のクラス定義は次の例のようになります。
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
- 括弧内の親クラスの順序に注意する必要があり、親クラスに同じメソッド名があり、それをサブクラスで使用するときに指定されていない場合、Pythonは左から右に検索します。メソッドがサブクラスで見つからない場合は、左から右に検索します。親クラスにメソッドが含まれているかどうか。
コード例
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中参数位置排前父类的方法
上記のプログラムを実行した出力結果は次のようになります。
私の名前はティムです。講演者です。講演のテーマは Python です。
メソッドのオーバーライド
親クラスのメソッドの機能がニーズを満たせない場合は、サブクラスで親クラスのメソッドをオーバーライドできます。例は次のとおりです。
#!/usr/bin/python3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
- super()関数は、親クラス(スーパークラス)を呼び出すためのメソッドです。
上記のプログラムを実行した出力結果は次のようになります。
サブクラスのメソッドを呼び出す
親クラスのメソッドを呼び出す
サブクラスで親クラスのコンストラクターが必要な場合は、親クラスのコンストラクターを明示的に呼び出すか、親クラスのコンストラクターをオーバーライドしない必要があります。
サブクラスは _ init _をオーバーライドしません。サブクラスをインスタンス化すると、親クラスによって定義された_ init _ が自動的に呼び出されます。
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name) )
def getName(self):
return 'Father ' + self.name
class Son(Father):
def getName(self):
return 'Son '+self.name
if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )
出力は次のとおりです。
名前:ルヌーブ
息子 ルヌーブ
_ init _がオーバーライドされ、サブクラスがインスタンス化される場合、親クラスによって定義された _ init _ は呼び出されません。構文形式は次のとおりです。
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name) )
def getName(self):
return 'Father ' + self.name
class Son(Father):
def __init__(self, name):
print ( "hi" )
self.name = name
def getName(self):
return 'Son '+self.name
if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )
出力は次のとおりです。
こんにちは、
息子ルヌーブ
_ init _ をオーバーライドし、親クラスのコンストラクター メソッドを継承したい場合は、superキーワードを使用できます。
super(子类,self).__init__(参数1,参数2,....)
古典的な書き方もあります。
父类名称.__init__(self,参数1,参数2,...)
コード例
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name))
def getName(self):
return 'Father ' + self.name
class Son(Father):
def __init__(self, name):
super(Son, self).__init__(name)
print ("hi")
self.name = name
def getName(self):
return 'Son '+self.name
if __name__=='__main__':
son=Son('tarzan')
print ( son.getName() )
出力は次のとおりです。
名前: ターザン
こんにちは、
息子ターザン
クラスのプロパティとメソッド
クラスのプライベートプロパティ
__private_attrs: 2 つのアンダースコアで始まり、属性がプライベートであり、クラス外で使用したり直接アクセスしたりできないことを宣言します。クラス内のメソッドで self.__private_attrs を使用する場合。
クラスメソッド
クラス内では、def キーワードを使用してメソッドを定義します。一般的な関数定義とは異なり、クラス メソッドには最初のパラメータであるパラメータ self が含まれている必要があります。Self はクラスのインスタンスを表します。
selfの名前は固定されておらず、これを使用することもできますが、規則に従ってself を使用するのが最善です。
クラスのプライベートメソッド
__private_method: 2 つのアンダースコアで始まるメソッドはプライベート メソッドとして宣言され、クラス外ではなくクラス内でのみ呼び出すことができます。self.__private_methods。
クラス
のプライベート プロパティの例は次のとおりです。
#!/usr/bin/python3
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量
上記のプログラムを実行した出力結果は次のようになります。
1
2
2
トレースバック (最新の呼び出しは最後):
ファイル “C:\Users\Lenovo\Desktop\test.py”、行 14、印刷中
(counter.__secretCount) # エラー、インスタンスはプライベート変数にアクセスできません
^^^^^ ^^^^^^^^^^^^^^^^
属性エラー: 'JustCounter' オブジェクトには属性 '__secretCount' がありません
クラスのプライベート メソッドの例は次のとおりです。
#!/usr/bin/python3
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self): # 公共方法
print('这是公共方法')
self.__foo()
x = Site('洛阳泰山博客', 'https://tarzan.blog.csdn.net')
x.who() # 正常输出
x.foo() # 正常输出
x.__foo() # 报错
上記のコードの実行出力は次のようになります。
name : 洛阳泰山博客
url : https://tarzan.blog.csdn.net
这是公共方法
这是私有方法
Traceback (most recent call last):
File "C:\Users\Lenovo\Desktop\test.py", line 22, in <module>
x.__foo() # 报错
^^^^^^^
AttributeError: 'Site' object has no attribute '__foo'
- 例外の理由 外部メソッドはプライベート メソッドを呼び出すことができません。
クラスのプライベート メソッド:
_ init _: オブジェクトの生成時に呼び出されるコンストラクター
_ del _: オブジェクトの解放時に使用されるデストラクター
_ repr _: 印刷、変換
_ setitem _: インデックスに従って値を割り当てる
_ getitem _: インデックスに従って値を取得
_ len _ : 長さの取得
_ cmp _: 比較演算
_ call _: 関数呼び出し
_ add _: 加算演算
_ sub _: 減算演算
_ mul _:乗算演算
_ truediv _: 除算演算
_ mod _: 剰余演算
_ pow _: 乗算四角
演算子のオーバーロード
Python は演算子のオーバーロードもサポートしています。クラスの独自メソッドをオーバーロードできます。例は次のとおりです。
#!/usr/bin/python3
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
上記のコードを実行した結果は次のようになります。
ベクトル(7,8)