8日目、オブジェクトに向かってステップアップ
17242 ワード
8日目、オブジェクトに向かってステップアップ
@(python)[メモ]
目次
一、isinstance()とissubclass()
1. isinstance()
構文:
2. issubclass()
構文:
二、反射
反射は主にプログラムがそれ自体の状態や行為にアクセス、検出、修正できる能力を指し、自省とも呼ばれる.
pythonオブジェクト向けの反射とは、オブジェクト関連のプロパティを文字列で操作することです.pythonのすべてのものはオブジェクトであり、反射を使用することができます.
pythonでは、自省できる4つの関数を実現します.
次の方法はクラスとオブジェクトに適用されます(すべてがオブジェクトであり、クラス自体もオブジェクトです).
1. hasattr()
構文:
2. getattr()
構文:
3. setattr()
構文:
4. delattr()
構文:delattr(x,y)機能:属性を削除し、
5.拡張用法
現在のモジュールを反射
他のモジュールをインポートし、そのモジュールにメソッドプログラムディレクトリがあるかどうかを反射で検索します. module_test.py current.py
三、
四、二次加工標準タイプ(包装)
パッケージ:pythonはユーザーに標準データ型と豊富な内蔵方法を提供しています.多くのシーンでは、標準データ型に基づいて自分のデータ型をカスタマイズし、新しい/書き換え方法をカスタマイズする必要があります.これは継承と派生の知識に使用され、他の標準タイプは以下の方法で二次加工することができます.
例1:
例2:
権限
ライセンスはパッケージの特性であり、パッケージのタイプは通常、既存のタイプのいくつかのカスタマイズであり、既存の製品の機能を新規、変更、または削除することができ、その他はそのままです.ライセンスのプロセスは、更新されたすべての機能が新しいクラスの一部で処理されますが、既存の機能はオブジェクトのデフォルトのプロパティにライセンスされます.
ライセンスの実現の鍵は、
例3:
例4:
例5:ライセンス方式で
要約:この方法は、カスタムソースがクラスではない場合に使用することを許可します.例3では、カスタム
五、
反復器には
シミュレーション実装range()関数:
六、
七、
次の2つのファイルは、同じレベルのディレクトリの下にあります.
八、
以上の2つのセグメントのコードから、私たちが自分で定義したクラスは、生成したオブジェクトが直接印刷されるとき、印刷されるのはオブジェクトのメモリアドレスであり、これは私たちが望んでいるものではありません.私たちが実際に望んでいるのも、最初のセグメントのコードのように有用な情報を返すことです.このとき、
九、
オブジェクトがメモリから解放されると、
注意:この方法は一般的に定義する必要はありません.Pythonは高度な言語であり、プログラマは使用時にメモリの割り当てと解放に関心を持つ必要はありません.この作業はPython解釈器に任せて実行されるため、構造関数の呼び出しは解釈器がゴミ回収を行うときに自動的にトリガーされます.
簡単な例:
次のような状況を見てみましょう.
十、
十一、 を表す. を表す.
例:open()をシミュレートし、コンテキスト管理を実現
十二、
十三、元類
@(python)[メモ]
目次
、isinstance() issubclass()
1. isinstance()
2. issubclass()
、
1. hasattr()
2. getattr()
3. setattr()
4. delattr()
5.
、__setattr__、__delattr__、__getattr__
、 ( )
、__next__ __iter__
、__doc__
、__module__ __class__
、__str__
、__del__
、__setitem__,__getitem__,__delitem__
、__enter__ __exit__
、__call__
、 metaclass
exec
一、isinstance()とissubclass()
1. isinstance()
構文:
isinstance(obj,cls)
機能:オブジェクトobjがクラスclsのインスタンスであるかどうかを確認します.class foo:
pass
obj = foo()
print(isinstance(obj,foo)) #True
2. issubclass()
構文:
issubclass(sub, super)
機能:subクラスがsuperクラスの派生クラス(サブクラス)であるかどうかを確認します.class foo:
pass
obj = foo()
print(isinstance(obj,foo)) #True
class bar(foo):
pass
print(issubclass(bar,foo)) #True
二、反射
反射は主にプログラムがそれ自体の状態や行為にアクセス、検出、修正できる能力を指し、自省とも呼ばれる.
pythonオブジェクト向けの反射とは、オブジェクト関連のプロパティを文字列で操作することです.pythonのすべてのものはオブジェクトであり、反射を使用することができます.
pythonでは、自省できる4つの関数を実現します.
次の方法はクラスとオブジェクトに適用されます(すべてがオブジェクトであり、クラス自体もオブジェクトです).
1. hasattr()
構文:
hasattr(object,"name")
機能:objectにname文字列に対応するメソッドまたは属性があるかどうかを判断します.使用方法:class foo:
name = "egon"
pass
obj = foo()
print(hasattr(obj,"name")) #True
print(hasattr(obj,"func")) #True
print(hasattr(foo,"name")) #True
print(hasattr(foo,"func")) #True
2. getattr()
構文:
getattr(object, "name"[, default=None])
機能:オブジェクトobjectからname文字列対応のメソッドを取得し、name文字列対応のメソッドがなく、defaultが設定されていない場合はエラーを報告します.name文字列に対応するメソッドがなくdefaultが設定されている場合、defaultの値が返されます.getattr(object,"name")
はobject.name
に等しいclass foo:
name = "egon"
def func(self):
print("Hello world")
obj = foo()
print(getattr(obj,"func"))
#>
# ,
f1 = getattr(obj,"func")
f2 = getattr(obj,"bar"," ")
f1() #Hello world
print(f2) #
3. setattr()
構文:
setattr(x, y, v)
機能:属性を設定し、setattr(x,'y',v)
は「x.y = v
」の使用法に等価です.class foo:
name = "egon"
def func(self):
print("Hello world")
obj = foo()
setattr(obj,"age",20)
setattr(obj,"show_name",lambda self:self.name+"_NB")
print(obj.__dict__) #
print(obj.show_name(obj))
'''
:
{'age': 20, 'show_name': at 0x000000000115E2F0>}
egon_NB
'''
4. delattr()
構文:delattr(x,y)機能:属性を削除し、
delattr(x,'y')
は``del x.y`'に相当する.delattr(obj,"show_name")
# delattr(obj,"sex") # ,
print(obj.__dict__) #{'age': 20}
5.拡張用法
現在のモジュールを反射
import sys
def s1():
print("s1")
def s2():
print("s2")
this_module = sys.modules[__name__]
print(hasattr(this_module,"s1")) #True
print(getattr(this_module,"s2"))
#,
他のモジュールをインポートし、そのモジュールにメソッドプログラムディレクトリがあるかどうかを反射で検索します.
# module_test.py
def test():
print("from the module_test.test")
#current.py
import module_test as mt
print(hasattr(mt,"test")) #True
f = getattr(mt,"test"," ")
f() #from the module_test.test
三、
__setattr__
、__delattr__
、__getattr__
__setattr__
:属性の追加/変更は、その実行をトリガーします.__delattr__
:属性を削除するとトリガーされます.__getattr__
:ポイント呼び出し属性が使用され、属性が存在しない場合にのみトリガーされます.class Foo:
x = 1
def __init__(self,y):
self.y = y
def __getattr__(self, item):
print("---> ")
def __setattr__(self, key, value):
print("---> from __setattr__")
# self.key = value # , __dict__
self.__dict__[key] = value #
def __delattr__(self, item):
print("---> from __delattr__")
f1 = Foo(10) # , __setattr__ ,---> from __setattr__
print(f1.__dict__)
#{}, , __setattr__ ,
# __setattr__
f1.z # __getattr__ ,--->
del f1.x # __delattr__ ,---> from __delattr__
四、二次加工標準タイプ(包装)
パッケージ:pythonはユーザーに標準データ型と豊富な内蔵方法を提供しています.多くのシーンでは、標準データ型に基づいて自分のデータ型をカスタマイズし、新しい/書き換え方法をカスタマイズする必要があります.これは継承と派生の知識に使用され、他の標準タイプは以下の方法で二次加工することができます.
例1:
list
を二次加工し、appendがint
の整数データしか増加できないことを制限する.mid
メソッドを追加し、リストの中間値を得る.残りの方法はlist
を継承します.class List(list):
def append(self,p_object):
# append , list append
if not isinstance(p_object,int):
raise TypeError("%s must be int"%p_object)
super(List, self).append(p_object)
@property
# , , property
def mid(self):
mid_num = len(self) // 2
return self[mid_num]
l = List([1,2,3,4])
print(l) #[1, 2, 3, 4]
l.append(5)
print(l) #[1, 2, 3, 4, 5]
print(l.mid) # 3
例2:
list
のclear
メソッドに権限を追加するclass List(list):
def __init__(self,item,perm=False):
super(List, self).__init__(item)
self.perm = perm
#
def clear(self):
if not self.perm:
raise PermissionError(" ")
super(List, self).clear()
l = List([1,2,3])
print(l) #[1, 2, 3]
# l.clear() # “ ”
l = List([1,2,3],True) # True
l.clear()
print(l) #[],
権限
ライセンスはパッケージの特性であり、パッケージのタイプは通常、既存のタイプのいくつかのカスタマイズであり、既存の製品の機能を新規、変更、または削除することができ、その他はそのままです.ライセンスのプロセスは、更新されたすべての機能が新しいクラスの一部で処理されますが、既存の機能はオブジェクトのデフォルトのプロパティにライセンスされます.
ライセンスの実現の鍵は、
__getattr__
を上書きする方法です.例3:
open()
関数を使用してファイルプロセッサを再カスタマイズし、書き込みコンテンツの追加時間を増やす機能.import time
class FileHandler:
def __init__(self,filename,mode='r',encoding="utf-8"):
self.file = open(filename,mode,encoding=encoding)
#self.file
def write(self,line):
t = time.strftime("%Y-%m-%d %X")
self.file.write("%s %s"%(t,line))
def __getattr__(self, item):
return getattr(self.file,item)
# FileHandler , open() item ;
f1 = FileHandler("a.txt","r+")
f1.write("
")
f1.seek(0)
print(f1.tell()) #0
例4:
# b
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
if 'b' in mode:
self.file=open(filename,mode)
else:
self.file=open(filename,mode,encoding=encoding)
self.filename=filename
self.mode=mode
self.encoding=encoding
def write(self,line):
if 'b' in self.mode:
if not isinstance(line,bytes):
raise TypeError('must be bytes')
self.file.write(line)
def __getattr__(self, item):
return getattr(self.file,item)
def __str__(self):
if 'b' in self.mode:
res="<_io.bufferedreader name="%s">" %self.filename
else:
res="<_io.textiowrapper name="%s" mode="%s" encoding="%s">" %(self.filename,self.mode,self.encoding)
return res
f1=FileHandle('b.txt','wb')
# f1.write(' ') # write, encode , ,
f1.write(' '.encode('utf-8'))
print(f1)
f1.close()
例5:ライセンス方式で
list
のappend
メソッドを再カスタマイズし、リストにint
の整数データしか追加できない.例と比較して、両者の違いを見てみましょう.
# , list
class List:
def __init__(self,seq):
self.seq = list(seq)
def append(self,p_object):
if not isinstance(p_object,int):
raise TypeError("'%s' must be int"%p_object)
self.seq.append(p_object)
def __getattr__(self, item):
return getattr(self.seq,item)
def __str__(self):
return str(self.seq)
l = List([1,2,3])
l.append("4") #TypeError: '4' must be int
print(l)
要約:この方法は、カスタムソースがクラスではない場合に使用することを許可します.例3では、カスタム
open()
関数五、
__next__
と__iter__
は反復器プロトコルを実現する反復器には
__next__
と__iter__
の方法が必要です.今すぐ自分で反復器を実現しましょう.シンプルな実装:class Foo:
def __init__(self,x):
self.x=x
def __iter__(self):
return self
def __next__(self):
n=self.x
self.x+=1
return self.x
f=Foo(3)
for i in f:
print(i)
シミュレーション実装range()関数:
class foo:
def __init__(self,start,stop=None,step=1):
self.start = start
self.stop = stop
self.step = step
if isinstance(self.start,str) \
or isinstance(self.stop,str) \
or isinstance(self.step,str):
raise InterruptedError("Must be Numeric")
def __next__(self):
if self.stop:
res = self.compute()
else:
self.stop = self.start
# ,
self.start = 0
# , 0
res = self.compute()
return res
def __iter__(self):
return self
# __iter__ ,
def compute(self):
if self.start >= self.stop:
#
raise StopIteration
#
iter_val = self.start #
self.start += self.step
return iter_val
for i in foo('a',20,3.5):
print(i)
for i in foo(5,15,3):
print(i)
六、
__doc__
オブジェクトの説明の表示def func():
''' '''
pass
print(func.__doc__)
class Foo:
''' '''
pass
class bar(Foo):
pass
obj = Foo()
print(obj.__doc__)
print(Foo.__doc__)
print(bar.__doc__) #
'''
:
None
'''
七、
__module__
と__class__
__module__
は、現在動作しているオブジェクトがそのモジュールにあることを示す__class__
現在操作されているオブジェクトのクラスが何であるかを示す次の2つのファイルは、同じレベルのディレクトリの下にあります.
#current.py
class C:
def __init__(self):
self.name = "alex"
#test.py
import current
def test():
print("from the test.test")
obj = current.C()
print(obj.name)
print(obj.__class__) #
print(obj.__module__) #
'''
:
alex
current
'''
八、
__str__
l = list([1,2,3])
print(l) # [1, 2, 3]
class mysql:
def __init__(self,host,port):
self.host = host
self.port = port
conn = mysql("127.0.0.1","3306")
print(conn) # <__main__.mysql object="" at="">
以上の2つのセグメントのコードから、私たちが自分で定義したクラスは、生成したオブジェクトが直接印刷されるとき、印刷されるのはオブジェクトのメモリアドレスであり、これは私たちが望んでいるものではありません.私たちが実際に望んでいるのも、最初のセグメントのコードのように有用な情報を返すことです.このとき、
__str__
という内蔵方法を使用します.それはクラスの内部に定義されています.クラスがインスタンス化されると、__str__
の実行が自動的にトリガーされ、インスタンス化されたオブジェクトに値が返されます.次の例を示します.class mysql:
def __init__(self,host,port):
self.host = host
self.port = port
def __str__(self):
return "Host:%s,Port:%s"%(self.host,self.port)
conn = mysql("127.0.0.1","3306")
# `__str__` conn
print(conn)
'''
:
Host:127.0.0.1,Port:3306
'''
九、
__del__
析構方法オブジェクトがメモリから解放されると、
__del__
が自動的にトリガーされます.注意:この方法は一般的に定義する必要はありません.Pythonは高度な言語であり、プログラマは使用時にメモリの割り当てと解放に関心を持つ必要はありません.この作業はPython解釈器に任せて実行されるため、構造関数の呼び出しは解釈器がゴミ回収を行うときに自動的にトリガーされます.
簡単な例:
class Foo:
def __del__(self):
print(" __del__")
f1 = Foo()
del f1 # f1, __del__
print("------->")
'''
:
__del__
------->
'''
次のような状況を見てみましょう.
class Foo:
def __del__(self):
print(" __del__")
f1 = Foo()
# del f1 #
print("------->")
'''
:
------->
__del__
'''
# __del__ ,
十、
__setitem__
、__getitem__
、__delitem__
クラスにはこの3つの方法があります.それは、クラスの属性が辞書のように操作できることを意味します.class Foo:
def __init__(self,name):
self.name = name
def __getitem__(self, item):
print("from __getitem__")
def __setitem__(self, key, value):
print("from __setitem__")
self.__dict__[key] = value # ,
def __delitem__(self, key):
print("from __delitem__")
self.__dict__.pop(key)
f1 = Foo("egon")
# f1.age = 18 # __setitem__
f1["age_2"] = 20 # __setitem__ , ;
print(f1.__dict__)
del f1["age_2"]
print(f1.__dict__)
print(f1["name"]) # __getitem__ , __getitem__ , None
'''
:
from __setitem__
{'name': 'egon', 'age_2': 20}
from __delitem__
{'name': 'egon'}
from __getitem__
None
'''
# ,age_2 = 20
十一、
__enter__
と__exit__
コンテキスト管理プロトコル、すなわち__enter__
文は、__exit__
およびwith
の2つの方法によって実現され得る.オブジェクトがwith
文と互換性を持つためには、__enter__
メソッドと__exit__
メソッドをこのオブジェクトのクラスに宣言する必要があります.class Open:
def __init__(self,name):
self.name = name
def __enter__(self):
# with , __enter__ , as
print("from __enter__")
return 3 # as
def __exit__(self, exc_type, exc_val, exc_tb):
print("from __exit__, with ")
with Open("egon") as f:
print("from with ")
print("f:",f)
'''
:
from __enter__
from with
f: 3
from __exit__, with
'''
__exit__(self, exc_type, exc_val, exc_tb)
の3つのパラメータの意味:exc_type
は異常タイプexc_val
は異常値exc_tb
異常を表すトレーサビリティ情報class Open:
def __init__(self,name):
self.name = name
def __enter__(self):
# with , __enter__ , as
# print("from __enter__")
return self # as
def __exit__(self, exc_type, exc_val, exc_tb):
print("from __exit__, with ")
print("exc_type:",exc_type)
print("exc_val:",exc_val)
print("exc_tb:",exc_tb)
return True # True, ,with , with raise 。
with Open("egon") as f:
print("from with ")
raise AttributeError(" ")
# print("=====> ") #
print("=====> ,with ") #__exit__ True
'''
:
from with
from __exit__, with
exc_type:
exc_val:
exc_tb:
=====>
'''
例:open()をシミュレートし、コンテキスト管理を実現
# open()
class Open:
def __init__(self,filename,mode='r',encoding="utf-8"):
self.filename = filename
self.mode = mode
self.encoding = encoding
def __enter__(self):
self.file = open(self.filename,self.mode,encoding =self.encoding)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
return True # ,with
with Open("a.txt","w+") as f:
f.write("11111
")
f.write("22222
")
f.seek(0)
print(f.tell())
f.abc # , __exit__
十二、
__call__
オブジェクトの後ろにカッコを付けると、__call__
メソッドの実行がトリガーされます.逆クラスには__call__
メソッドがあり、このクラスで生成されたオブジェクトによってカッコを付けて実行できます.class foo:
def __init__(self):
print("from __init__")
def __call__(self, *args, **kwargs):
print("from __call__")
obj = foo() # __init__
obj() # __call__
'''
:
from __init__
from __call__
'''
十三、元類
metaclass
まずexec
を見てみましょう