Python3オブジェクト指向
言うまでもありませんが、最初にたくさんの理論的な知識を取得しましょう。ctrl+ Fを使用するだけです。
Pythonは、その設計以来オブジェクト指向言語であり、このため、Pythonでクラスとオブジェクトを簡単に作成できます。この章では、Pythonのオブジェクト指向プログラミングについて詳しく紹介します。
これまでオブジェクト指向プログラミング言語に触れたことがない場合は、オブジェクト指向言語の基本的な機能のいくつかを理解し、基本的なオブジェクト指向の概念を頭の中で形成する必要があるかもしれません。これは、学習に役立ちます。 Pythonをより簡単に。オブジェクト指向プログラミング。
次に、次のオブジェクトの基本的な特性のいくつかを簡単に理解しましょう。
オブジェクト指向技術の紹介
- クラス: 同じプロパティとメソッドを持つオブジェクトのコレクションを記述するために使用されます。コレクション内の各オブジェクトに共通の属性とメソッドを定義します。オブジェクトはクラスのインスタンスです。
- メソッド:クラスで定義された関数。
- クラス変数:クラス変数は、インスタンス化されたオブジェクト全体に共通です。クラス変数は、クラス内および関数本体の外部で定義されます。クラス変数は通常、インスタンス変数として使用されません。
- データメンバー:クラス変数またはインスタンス変数は、クラスとそのインスタンスオブジェクトに関連するデータを処理するために使用されます。
- メソッドの書き換え:親クラスから継承されたメソッドが子クラスのニーズを満たせない場合は、書き換えることができます。このプロセスはメソッドのオーバーライドと呼ばれ、メソッドの書き換えとも呼ばれます。
- ローカル変数:メソッドで定義された変数は、現在のインスタンスのクラスにのみ作用します。
- インスタンス変数:クラスの宣言では、属性は変数で表されます。このような変数はインスタンス変数と呼ばれ、クラス宣言の内部で宣言されますが、クラスの他のメンバーメソッドの外部で宣言されます。
- 継承:つまり、派生クラスは基本クラスのフィールドとメソッドを継承します。継承により、派生クラスのオブジェクトを基本クラスオブジェクトとして扱うこともできます。たとえば、そのような設計があります。タイプDogのオブジェクトは、「is-a」関係をシミュレートするAnimalクラスから派生します(図の例、Dogは動物です)。
- インスタンス化:クラスの特定のオブジェクトであるクラスのインスタンスを作成します。
- オブジェクト:クラスによって定義されたデータ構造のインスタンス。オブジェクトには、2つのデータメンバー(クラス変数とインスタンス変数)とメソッドが含まれます。
他のプログラミング言語と比較して、Pythonは、新しい構文やセマンティクスを可能な限り追加せずに、クラスメカニズムを追加します。
Pythonのクラスは、オブジェクト指向プログラミングのすべての基本機能を提供します。クラスの継承メカニズムにより、複数の基本クラスが可能になり、派生クラスは基本クラスの任意のメソッドをカバーでき、基本クラスの同じ名前のメソッドをで呼び出すことができます。メソッド。
オブジェクトには、任意の量とタイプのデータを含めることができます。
クラス固有のメソッド:
- __init __: コンストラクター。オブジェクトの生成時に呼び出されます
- __del__: オブジェクトを解放するときに使用されるデストラクタ
- __repr__: 印刷、変換
- __setitem__: インデックスに従って値を割り当てます
- __getitem__: インデックスに従って値を取得します
- __len__: 長さを取得します
- __cmp__: 比較演算
- __call__: 関数呼び出し
- __add__: 加算演算
- __sub__: 減算演算
- __mul__: 乗算
- __truediv__: 除算演算
- __mod__: 剰余演算
- __pow__: 力
针对 __str__ 方法给出一个比较直观的例子:
class people:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '这个人的名字是%s,已经有%d岁了!'%(self.name,self.age)
a=people('孙悟空',999)
print(a)
输出:
这个人的名字是孙悟空,已经有999岁了!
如果没有重载函数的话输出的就是一串看不懂的字符串:
<__main__.people object at 0x00000272A730D278>
最新的 Python3.7 中(2018.07.13),对类的构造函数进行了精简。
3.7 版本:
from dataclasses import dataclass
@dataclass
class A:
x:int
y:int
def add(self):
return self.x + self.y
相当于以前的:
class A:
def __init__(self,x,y):
self.x = x
self.y = y
def add(self):
return self.x + self.y
静态方法: 用 @staticmethod 装饰的不带 self 参数的方法叫做静态方法,类的静态方法可以没有参数,可以直接使用类名调用。
普通方法: 默认有个self参数,且只能被对象调用。
类方法: 默认有个 cls 参数,可以被类和对象调用,需要加上 @classmethod 装饰器。
class Classname:
@staticmethod
def fun():
print('静态方法')
@classmethod
def a(cls):
print('类方法')
# 普通方法
def b(self):
print('普通方法')
Classname.fun()
Classname.a()
C = Classname()
C.fun()
C.a()
C.b()
selfeasy
selfeasy
反向运算符重载:
__radd__: 加运算
__rsub__: 减运算
__rmul__: 乘运算
__rdiv__: 除运算
__rmod__: 求余运算
__rpow__: 乘方
复合重载运算符:
__iadd__: 加运算
__isub__: 减运算
__imul__: 乘运算
__idiv__: 除运算
__imod__: 求余运算
__ipow__: 乘方
运算符重载的时候:
#!/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 __repr__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
if other.__class__ is Vector:
return Vector(self.a + other.a, self.b + other.b)
elif other.__class__ is int:
return Vector(self.a+other,self.b)
def __radd__(self,other):
"""反向算术运算符的重载
__add__运算符重载可以保证V+int的情况下不会报错,但是反过来int+V就会报错,通过反向运算符重载可以解决此问题
"""
if other.__class__ is int or other.__class__ is float:
return Vector(self.a+other,self.b)
else:
raise ValueError("值错误")
def __iadd__(self,other):
"""复合赋值算数运算符的重载
主要用于列表,例如L1+=L2,默认情况下调用__add__,会生成一个新的列表,
当数据过大的时候会影响效率,而此函数可以重载+=,使L2直接增加到L1后面
"""
if other.__class__ is Vector:
return Vector(self.a + other.a, self.b + other.b)
elif other.__class__ is int:
return Vector(self.a+other,self.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
print (v1+5)
print (6+v2)
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 say : i am %d."%(self.name,self.age))
p = People('Python',10,20)
p.speak()
# __weight无法直接访问
print(p.name,'--',p.age)#,'--',p.__weight)
继承
单继承:
class Student(People):
grade=''
def __init__(self,n,a,w,g):
People.__init__(self,n,a,w)
self.grade = g
# 覆写父类方法
def speak():
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
class Speak():
topic=''
name=''
def __init__(self,n,t):
self.name = n
self.topic = t
# 普通方法,对象调用
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
# 私有方法,self调用
def __song(self):
print('唱一首歌自己听',self);
# 静态方法,对象和类调用,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
@staticmethod
def song():
print('唱一首歌给类听:静态方法');
# 普通方法,对象调用
def song(self):
print('唱一首歌给你们听',self);
# 类方法,对象和类调用,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
@classmethod
def song(self):
print('唱一首歌给类听:类方法',self)
多继承:
class Sample(Speak,Student):
a = ''
def __init__(self,n,a,w,g,t):
Student.__init__(self,n,a,w,g)
Speak.__init__(self,n,t)
test = Sample('Song',24,56,7,'Python')
test.speak()
test.song()
Sample.song()
Sample.song()
test.song()
# test.__song() 无法访问私有方法
类的二元方法运算符重载介绍的并不全面,文中介绍的全是正向方法,其实还有反向方法,就地方法。下面补充一些。
当解释器碰到 a+b 时,会做以下事情:
从 a 类中找 __add__ 若返回值不是 NotImplemented, 则调用 a.__add__(b)。
若 a 类中没有 __add__ 方法,则检查 b 有没有 __radd__ 。如果如果有,则调用 b.__radd__(a),若没有,则返回 NotImplemented。
接上条,若 b 也没有 __radd__ 方法,则抛出 TypeError,在错误消息中知名操作数类型不支持。
比如:向量类 <Myvector> 应当有向量与整数的乘法:
>>>a = Myvector([1,2,3])
>>>print(a.value)
[1,2,3]
>>>b=3
>>>c = a*b #此时调用Myvector.__mul__()
>>>print(c.value)
[3,6,9]
>>> d=b*a #这句会出错。
期望得到 b*a 也返回一个向量,b*a 应该等于 a*b。此时就需要在 Myvector 类中定义一个__rmul__方法。
def __rmul__(self, other):
if isinstance(other, int):
return Myvector([a*other for a in self.m])
每个运算符都有正向方法重载,反向方法重载。有一些有就地方法(即不返回新的对象,而是修改原本对象)。
class Ren:
name ="zhangsan"
age =20
sex ='man'
def run(self):
print 'basketball'
class Ren:
name ="zhangsan" #变量
age =20
sex ='man'
def run(self,x): #函数
print 'basketball'
print x
zhang =Ren() #创建对象的过程叫实例化,zhang为对象
print zhang.name
zhang.run('xxxxxxxxxx') #对象的方法
zhang.age =40 #设置属性
print zhang.age
zhang.job ='it' #添加属性
print zhang.job
class Ren:
name ="zhangsan" #变量
age =20
sex ='man'
__tt ='zs'
def run(self,x): #函数
print 'basketball'
print x
print self.__tt #内部调用私有属性
zhang =Ren()
print zhang.name
zhang.run('xxxxxxxxxx')
zhang.age =40
print zhang.age
zhang.job ='it'
print zhang.job
print zhang._Ren__tt #调用内部私有类
#! /usr/bin/python
# ! -*- coding: UTF-8 -*-
class Ren:
name = "zhangsan" # 变量
age = 20
sex = 'man'
__tt = 'zs'
def run(self, x): # 函数
print 'basketball'
print x
print self.__tt # 内部调用私有属性
def __kk(self, x): # 函数
print 'running'
print self.__tt # 内部调用私有属性
@classmethod #函数修饰符 或者声明称静态函数@staticmethod,静态函数就不需要加参数了,即无须self
def hel(self): #@classmethod 相当于把run函数加载到classmethod里面运行,即run =@classmethod(run)
print "hel man!" # 使用私有方法进行调用测试
zhang = Ren() # 创建对象的过程叫实例化,zhang为对象
print zhang.name
zhang.run('xxxxxxxxxx') # 对象的方法
zhang.age = 40 # 设置属性
print zhang.age
zhang.job = 'it' # 添加属性
print zhang.job
print zhang._Ren__tt # 调用内部私有类
zhang._Ren__kk("私有方法调用")
zhang.hel() # 公有方法
Ren.hel() #私有方法调用
class Ren:
class Badren:#Internal class
name = 'huairen'
@classmethod
def badshi(self):
print'papapa '
huairen = Ren.Badren#内部クラスの
インスタンス化print huairen.name#内部クラスの変数について
huairenを呼び出す.badshi()#
class Ren:
def __init __(self、x):
print 'コンストラクター:オブジェクトをインスタンス化するとき、コンストラクターはデフォルトで実行されます。つまり、インスタンス化するときは、最初にコンストラクターを呼び出します
' print'xxxxxxxxxx: '、x#インスタンス化するときオブジェクトにパラメータを渡し、コンストラクタを介して実装します
zhang = Ren( "zhangsan")#オブジェクトをインスタンス化するときは、パラメータをオブジェクトに渡し、コンストラクタを介して実装します
#f = open( 'c:\ 1.txt'、 'r')#読み取り専用形式で、関数f、ファイル操作をインスタンス化します
class Ren:
name = "zhangsan" # 变量
age = 20
sex = 'man'
__tt = 'zs'
def __del__(self): #析构函数
f = open('c:\1.txt', 'r')
f.read()
f.close()
class Parent:
name ='lisi'
parentAttr = 100
def fulei(self):
print '这是父类中的方法'
def __init__(self):
print "这是父类中构造函数,私有化方法"
class Child(Parent):#子类调用父类
name ='lisi'
def childMethod(self):
print '这是子类中的方法'
child =Child()#实例化子类
child.fulei()#子类调用父类中的方法
child.childMethod()#调用子类中本身的方法
print child.name #(子类父类中同有的变量),子类调用时,优先权会高于父类,输出lisi
レッスン13の合計コード:
#! /usr/bin/python
# ! -*- coding: UTF-8 -*-
#【继承】
#父类有的,继承后子类可以直接调用
#父类子类都有同一个重名函数,优先子类调用自己的
#父类只能调用自己的函数
class Ren:
name = "zhangsan" # 变量
age = 20
sex = 'man'
__tt = 'zs'
def __del__(self): #析构函数
f = open('c:\1.txt', 'r')
f.read()
f.close()
'''
def __init__(self,x):
print '构造函数:当实例化对象的时候,构造函数就会被默认执行,即实例化的时候,先调用构造函数'
print 'xxxxxxxxxx:',x #实例化对象的时候,对其进行传参,通过构造函数实现
zhang =Ren("zhangsan")#实例化对象的时候,对其进行传参,通过构造函数实现
#f =open('c:\1.txt','r') #以只读的形式,实例化函数f ,文件操作
def run(self, x): # 函数
print 'basketball'
print x
print self.__tt # 内部调用私有属性
def __kk(self, x): # 函数
print 'running'
print self.__tt # 内部调用私有属性
@classmethod #函数修饰符 或者声明称静态函数@staticmethod,静态函数就不需要加参数了,即无须self
def hel(self): #@classmethod 相当于把run函数加载到classmethod里面运行,即run =@classmethod(run)
print "hel man!" # 使用私有方法进行调用测试
class Badren: #内部类
name ='huairen'
@classmethod
def badshi(self):
print 'papapa'
zhang = Ren() # 创建对象的过程叫实例化,zhang为对象
print zhang.name
zhang.run('xxxxxxxxxx') # 对象的方法
zhang.age = 40 # 设置属性
print zhang.age
zhang.job = 'it' # 添加属性
print zhang.job
print zhang._Ren__tt # 调用内部私有类
zhang._Ren__kk("私有方法调用")
zhang.hel() # 公有方法
Ren.hel() #私有方法调用
huairen =Ren.Badren #对内部类进行实例化 或者是huairen=zhang.Badren
print huairen.name #对内部类里面的变量进行调用
huairen.badshi() #对内部类的方法进行调用
'''
class Parent:
name ='lisi'
parentAttr = 100
def fulei(self):
print '这是父类中的方法'
def __init__(self):
print "这是父类中构造函数,私有化方法"
class Child(Parent):#子类调用父类
name ='lisi'
def childMethod(self):
print '这是子类中的方法'
child =Child()#实例化子类
child.fulei()#子类调用父类中的方法
child.childMethod()#调用子类中本身的方法
print child.name #(子类父类中同有的变量),子类调用时,优先权会高于父类,输出lisi
class sson(Child):
print '我是孙子类,测试能否继承爷爷类'
sson =sson()#并且实例化对象时,会再次加载构造函数
sson.fulei()# 结果测试可以继承
示してください:Adminxeのブログ » 0x013。Python学習-オブジェクト指向