pythonのアクセサリー、魔法のプロパティ、withと「コンテキストマネージャ」
18267 ワード
Pythonのクローズ
デコレーション
新しいクラス、3種類の@property装飾器を備えています
[関数|クラス]をカスタマイズしたアクセラレータ
関数の装飾器、関数の呼び出し方式を修正しないで、依然として出力を修正することができます
モディファイヤにパラメータを渡すには
*argsで任意のパラメータを入力できます
アクセラレータが戻り値を受け取る
装飾器の最終形態、*kwはキーワードパラメータを表し、余分なキーワードは辞書として印刷されます.
コード実装を破壊せず、コード多重性を実現し、複数のアクセサリーを積み重ねて使用できる
複数のアクセサリが同じ関数を装飾する
アクセサリー類
デコレーションパラメータ
装飾器、タイプ検出に変更し、不一致が検出された場合はprintと書き込みなし
@propertyとは、装飾されたクラスや関数をパラメータとしてproperty(クラス)に入力し、実行後に装飾されたクラスに戻り値を割り当てます.以下はカスタム@propertyで、オリジナルの@propertyと似た機能があります
Pythonの魔法属性
構造関数
printは
カスタム
反復メソッド、
カスタム
withと「コンテキストマネージャ」、関数トリガenterとexit
コンテキストマネージャ
例外情報の場合
def deco(x, y):
def wrapper(z):
return x+y+z
return wrapper
d = deco(100, 200)
print(d(300)) // 600
: 、 、 、 ?
1. ,,,
2. ,,,
3. ,,, , +
4. ,,, + , +
デコレーション
property
,
class Goods:
@property
def size(self):
return 100
g = Goods()
print(g.size) # 100
Python property :property , 。
, ,
,
def current_func(func):
func()
def f1():
print('This is a function-1')
def f2():
print('This is a function-2')
current_func(f1)
current_func(f2)
:
This is a function-1
This is a function-2
新しいクラス、3種類の@property装飾器を備えています
class Goods:
"""python3 object
python2、3 , python3 @xxx.setter @xxx.deleter
"""
@property
def size(self):
return 100
@size.setter
def size(self, value):
print("@size.setter")
@size.deleter
def size(self):
print("@size.deleter")
g = Goods()
print(g.size) @property price ,
g.size = 200 @price.setter price , 200
del g.size @price.deleter price
property setter,deleter
:
class Goods:
def __init__(self):
self.__money = 200
def get_money(self):
print("get __money")
return self.__money
def set_money(self, value):
print("set __money")
self.__money = value
def del_size(self):
print("del __money")
del self.__money
m = property(get_money, set_money, del_size)
g = Goods()
print(g.m)
g.m = 500
del g.m
:
get __money
200
set __money
del __money
[関数|クラス]をカスタマイズしたアクセラレータ
関数の装飾器、関数の呼び出し方式を修正しないで、依然として出力を修正することができます
def deco(func):
print(" ------")
def wrapper():
print(" 1 2 3")
func()
return wrapper
deco test func deco, test
@deco # test = deco(test)
def test():
print("test function")
print(" ---")
test()
:
------
---
1 2 3
test function
Python @deco ,
モディファイヤにパラメータを渡すには
def deco(func):
def wrapper(name):
print(" 1 2 3")
func(name)
return wrapper
@deco # test = deco(test)
def test(name):
print("name = " + name)
test("libai")
:
1 2 3
name = libai
*argsで任意のパラメータを入力できます
def decorator(func):
def wrapper(*args): //
func(*args)
return wrapper
@decorator
def f0():
print("no args")
@decorator
def f1(name):
print("name = " + name)
@decorator
def f2(name, age):
print("name = " + name + ", age = " + str(age))
f0()
f1("libai")
f2('libai', 22)
:
no args
name = libai
name = libai, age = 22
アクセラレータが戻り値を受け取る
def deco(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs) // return
return wrapper
@deco
def test(name):
print("name = " + name)
return "hello"
ret = test("libai")
print(ret)
:
name = libai
hello
装飾器の最終形態、*kwはキーワードパラメータを表し、余分なキーワードは辞書として印刷されます.
def decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
コード実装を破壊せず、コード多重性を実現し、複数のアクセサリーを積み重ねて使用できる
複数のアクセサリが同じ関数を装飾する
def deco_1(func):
print("---- -1----")
def wrapper(*args, **kwargs):
print("---- -1-- ----")
return func(*args, **kwargs)
return wrapper
def deco_2(func):
print("---- -2----")
def wrapper(*args, **kwargs):
print("---- -2-- ----")
return func(*args, **kwargs)
return wrapper
@deco_1
@deco_2 // deco_2, deco_1
def test(name):
print("name = " + name)
test("libai")
:
---- -2----
---- -1----
---- -1-- ----
---- -2-- ----
name = libai
アクセサリー類
class Test():
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(" __call__ ")
return self.func(*args, **kwargs)
@Test
def func(name):
print("name = " + name)
func("libai")
:
__call__
name = libai
デコレーションパラメータ
def set_level(level):
def deco(func):
def inner(*args, **kwargs):
if level == 1:
print("---- --1-- ----")
elif level == 2:
print("---- --3-- ----")
else:
print("---- --3-- ----")
func(*args, **kwargs)
return inner
return deco
@set_level(1)
def test(name):
print("name = " + name)
test("1000")
:
---- --1-- ----
name = 1000
装飾器、タイプ検出に変更し、不一致が検出された場合はprintと書き込みなし
def deco(**kwargs): # **kwargs
def wrapper(obj): # wrapper earth
print('========================')
for key,value in kwargs.items(): # .items()
setattr(obj, key, Type(key, value))
return obj
print(kwargs)
return wrapper
#
class Type:
def __init__(self, key, except_type):
self.key = key
self.except_type = except_type
def __get__(self, instance, owner):
print('get ')
print(instance)
print(owner)
return instance.__dict__[self.key]
def __set__(self, instance, value):
print('set ')
print(instance)
print(value)
if not isinstance(value,self.except_type):
print(" %s " %self.except_type)
return
instance.__dict__[self.key] = value
def __delete__(self, instance):
print('del ')
print(instance)
del instance.__dict__[self.key]
@deco(name=str,age=int) #name str,age int
class earth:
def __init__(self, name, age):
self.name = name
self.age = age
e = earth('libai', '23') # set
print('*************************************************')
print(earth.__dict__)
print(e.__dict__)
:
{'name': , 'age': }
========================
set
<__main__.earth object="" at="">
libai
set
<__main__.earth object="" at="">
23
*************************************************
{'__module__': '__main__', '__init__': , '__dict__': , '__weakref__': , '__doc__': None, 'name': <__main__.type object="" at="">, 'age': <__main__.type object="" at="">}
{'name': 'libai'}
@propertyとは、装飾されたクラスや関数をパラメータとしてproperty(クラス)に入力し、実行後に装飾されたクラスに戻り値を割り当てます.以下はカスタム@propertyで、オリジナルの@propertyと似た機能があります
class Lazyproperty:
def __init__(self, func):
self.func = func
print('func = ', self.func)
def __get__(self, instance, owner):
print('instance = ', instance)
print('owner = ', owner)
# self.func(instance) print ,
# test , test
print('------------------>>>', self.func(instance))
print('***************************************************')
return self.func(instance)
class earth:
def __init__(self):
pass
@Lazyproperty
def test(self):
print('test')
return ' ?'
e = earth()
print(e.test)
:
func =
instance = <__main__.earth object="" at="">
owner =
test
------------------>>> ? # test
***************************************************
test
?
Pythonの魔法属性
__doc__
はクラスの記述情報を表し、この属性は継承できないclass Foo:
""" , """
def func(self):
pass
class Son(Foo): # __doc__
pass
f = Foo()
print(Foo.__dict__)
print(Son.__dict__)
print(f.__dict__)
:
{'__module__': '__main__', '__doc__': ' , ', 'func': , '__dict__': , '__weakref__': }
{'__module__': '__main__', '__doc__': None}
{}
__module__
および__class__
__module__
__class__
test.py
class Person(object):
def __init__(self):
self.name = 'laowang'
main.py
from test import Person
obj = Person()
print(obj.__module__) # test : Person
print(obj.__class__) # test.Person : Person
__init__
初期化方法 , ,
class Person:
def __init__(self, name):
self.name = name
self.age = 18
obj = Person('laowang') # __init__
構造関数
__del__
オブジェクトがメモリから解放されると、自動的に実行がトリガーされ、インスタンスがシステムによって回収されるとトリガーされる , 。
: , Python , ,
Python , ,__del__ 。
class earth:
def __init__(self):
self.name = 'libai'
def __del__(self):
print('del is work')
e = earth()
print(e.name)
del e.name __del__
print("program end")
, __del__
:
libai
program end
del is work
__call__
オブジェクトの後ろに括弧を付け、実行をトリガーします. , 。
:__init__ , : = () ; __call__ , : () ()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() __init__
obj() __call__, Foo __call__
__dict__
クラスまたはオブジェクトのすべてのプロパティ
; , :
class Province(object):
country = 'China'
def __init__(self, name, count):
self.name = name
self.count = count
def func(self, *args, **kwargs):
print('func')
, : 、 、
print(Province.__dict__)
:{'__dict__': , '__module__': '__main__', 'country': 'China', '__doc__': None, '__weakref__': , 'func': , '__init__': }
obj1 = Province(' ', 10000)
print(obj1.__dict__)
obj1
:{'count': 10000, 'name': ' '}
obj2 = Province(' ', 20000)
print(obj2.__dict__)
obj1
:{'count': 20000, 'name': ' '}
__str__
このメソッドの戻り値は、オブジェクトの印刷時にデフォルトで出力されます. __str__ ,print() __str__ , 。
class Foo:
def __str__(self):
return 'laowang'
obj = Foo()
print(obj)
:laowang
printは
__str__
メソッドを呼び出し、__repr__
はインタラクティブインタフェースが返す値である.カスタム
__repr__
メソッドから、__repr__
と__str
が同時に存在する場合、__str__
メソッドが実行され、__str__
が存在しない場合、__repr__
が実行されるclass test:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return ' %s, %s' %(self.name, self.age)
def __repr__(self):
return "return repr"
t = test('libai', 20)
print(t)
:
libai, 20
反復メソッド、
__iter__
および__next__
class Fib():
def __init__(self):
self.a = 0
self.b = 1
def __iter__(self): # , , __iter__
print("run __iter__ function")
return self
def __next__(self):
self.a, self.b = self.b, self.a+self.b
if self.a > 10:
raise StopIteration(' ') # for StopIteration , next()
return self.a,self.b
f = Fib()
print(next(f))
print(next(f))
print('==========================')
for i in f:
print(i, end=", ")
:
(1, 1)
(1, 2)
==========================
run __iter__ function
(2, 3), (3, 5), (5, 8), (8, 13),
__getitem__
、 __setitem__
、 __delitem__
, 。 、 、
class Foo(object):
def __getitem__(self, key):
print('__getitem__', key)
def __setitem__(self, key, value):
print('__setitem__', key, value)
def __delitem__(self, key):
print('__delitem__', key)
obj = Foo()
result = obj['k1'] # __getitem__
obj['k2'] = 'laowang' # __setitem__
del obj['k1'] # __delitem__
__getslice__
、 __setslice__
、 __delslice__
, :
class Foo(object):
def __getslice__(self, i, j):
print('__getslice__', i, j)
def __setslice__(self, i, j, sequence):
print('__setslice__', i, j)
def __delslice__(self, i, j):
print('__delslice__', i, j)
obj = Foo()
obj[-1:1] # __getslice__
obj[0:1] = [11,22,33,44] # __setslice__
del obj[0:2] # __delslice__
__getattribute__
プロパティで、プログラムのクラッシュを防止class Earth:
def __init__(self, name):
self.name = name
def __getattr__(self, item):
print("getattr is work,get the ", item)
__getattribute__ , __getattribute__ __getattr__
def __getattribute__(self, item):
print('getattribute is work, get the ', item)
raise AttributeError(" ") # , ,raise __getattr__
e = Earth('game')
e.name
e.none
:
getattribute is work, get the name #name
getattr is work,get the name
getattribute is work, get the none #none
getattr is work,get the none
カスタム
__format__
メソッド、フォーマット出力format_dict = {
'ymd' : '{0.year} {0.mon} {0.day}',
'y-m-d' : '{0.year}-{0.mon}-{0.day}',
'y:m:d' : '{0.year}:{0.mon}:{0.day}'
}
class Date:
def __init__(self, year, mon, day):
self.year = year
self.mon = mon
self.day = day
def __format__(self, format_spec):
print("my format, format_spec = '%s'" %format_spec)
if format_spec and format_spec in format_dict:
return format_dict[format_spec].format(self)
else:
return format_dict['ymd'].format(self)
d = Date(2018, 4, 18)
print('{0.year} {0.mon} {0.day}'.format(d)) #
print(format(d, 'none')) #
print(format(d, 'y-m-d'))
print(format(d, 'y:m:d'))
:
my format, format_spec = 'none'
2018 4 18
my format, format_spec = 'y-m-d'
2018-4-18
my format, format_spec = 'y:m:d'
2018:4:18
withと「コンテキストマネージャ」、関数トリガenterとexit
with open("output.txt", "r") as f:
f.write("Python ")
try/finally
f = open("output.txt", "w")
try:
f.write("python ")
except IOError:
print("oops error")
finally:
f.close()
、 with 。open f, with
, f.close() , with try/finally 。
? with ,
(Context Manager)。
コンテキストマネージャ
__enter__() __exit__() ,
with 。 , (file) 。
? ,
__enter__() __exit__() 。
class File():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self): #
print("entering")
self.f = open(self.filename, self.mode)
return self.f
def __exit__(self, *args): #
print("will exit")
self.f.close()
__enter__() , ,
__exit__() 。
File , with 。
with File('out.txt', 'w') as f:
print("writing")
f.write('hello, python')
, close , ,
close 。
1.with File ---> File.__enter__(),
2.as f -----> f=
3.with File as f f=File.__enter__()
4.
: , __exit__, none
: , __exit__
a: __exit__ True,
b: __exit__ True,
c: __exit__ with
Python with , try/finally ,
。
例外情報の場合
>>> abc
Traceback (most recent call last):
File "", line 1, in
NameError: name 'abc' is not defined
NameError ----->class
name 'abc' is not defined ----->
Traceback ----->