日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python3.7用法_Python 3.7中dataclass装饰器用法详解

發布時間:2024/9/18 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python3.7用法_Python 3.7中dataclass装饰器用法详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python 3.7的dataclass裝飾器用法

Python 3.7新功能之dataclass裝飾器詳解

前言

Python 3.7 將于今年夏天發布,Python 3.7 中將會有許多新東西:

各種字符集的改進

對注釋的推遲評估

以及對dataclass的支持

最激動人心的新功能之一是 dataclass 裝飾器。

什么是 Data Class

大多數 Python 開發人員編寫過很多像下面這樣的類:

class MyClass:

def __init__(self, var_a, var_b):

self.var_a = var_a

self.var_b = var_b

dataclass 可以為簡單的情況自動生成方法,例如,一個__init__接受這些參數并將其分配給自己,之前的小例子可以重寫為:

@dataclass

class MyClass:

var_a: str

var_b: str

那么通過一個例子來看看如何使用吧

星球大戰 API

可以使用 requests 從星球大戰 API 獲取資源:

response = requests.get('https://swapi.co/api/films/1/')

dictionary = response.json()

讓我們來看看 dictionary (簡化過)的結果:

{

'characters': ['https://swapi.co/api/people/1/',… ],

'created': '2014-12-10T14:23:31.880000Z',

'director': 'George Lucas',

'edited': '2015-04-11T09:46:52.774897Z',

'episode_id': 4,

'opening_crawl': 'It is a period of civil war.\r\n … ',

'planets': ['https://swapi.co/api/planets/2/', … ],

'producer': 'Gary Kurtz, Rick McCallum',

'release_date': '1977-05-25',

'species': ['https://swapi.co/api/species/5/',…],

'starships': ['https://swapi.co/api/starships/2/',…],

'title': 'A New Hope',

'url': 'https://swapi.co/api/films/1/',

'vehicles': ['https://swapi.co/api/vehicles/4/',…]

封裝 API

為了正確地封裝一個 API,我們應該創建一個用戶可以在其應用程序中使用的對象,因此,在Python 3.6 中定義一個對象來包含requests對 /films/endpoint的響應:

class StarWarsMovie:

def __init__(self,

title: str,

episode_id: int,

opening_crawl: str,

director: str,

producer: str,

release_date: datetime,

characters: List[str],

planets: List[str],

starships: List[str],

vehicles: List[str],

species: List[str],

created: datetime,

edited: datetime,

url: str

):

self.title = title

self.episode_id = episode_id

self.opening_crawl= opening_crawl

self.director = director

self.producer = producer

self.release_date = release_date

self.characters = characters

self.planets = planets

self.starships = starships

self.vehicles = vehicles

self.species = species

self.created = created

self.edited = edited

self.url = url

if type(self.release_date) is str:

self.release_date = dateutil.parser.parse(self.release_date)

if type(self.created) is str:

self.created = dateutil.parser.parse(self.created)

if type(self.edited) is str:

self.edited = dateutil.parser.parse(self.edited)

仔細的讀者可能已經注意到這里有一些重復的代碼。

這是使用 dataclass 裝飾器的經典案例,我們需要創建一個主要用來保存數據的類,只需一點驗證,所以讓我們來看看我們需要修改什么。

首先,data class 自動生成一些 dunder 方法,如果我們沒有為 data class 裝飾器指定任何選項,則生成的方法有:__init__,__eq__和__repr__,如果你已經定義了__repr__但沒定義__str__,默認情況下 Python(不僅僅是 data class)將實現返回__repr__的輸出__str__方法。因此,只需將代碼更改為以下代碼即可實現四種 dunder 方法:

@dataclass

class StarWarsMovie:

title: str

episode_id: int

opening_crawl: str

director: str

producer: str

release_date: datetime

characters: List[str]

planets: List[str]

starships: List[str]

vehicles: List[str]

species: List[str]

created: datetime

edited: datetime

url: str

我們去掉了__init__方法,以確保 data class 裝飾器可以添加它生成的對應方法。不過,我們在這個過程中失去了一些功能,我們的 Python 3.6 構造函數不僅定義了所有的值,還試圖解析日期,我們怎樣才能用 data class 來做到這一點呢?

如果要覆蓋 __init__,我們將失去 data class 的優勢,因此,如果要處理任何附加功能可以使用新的 dunder 方法:__post_init__,讓我們看看__post_init__方法對于我們的包裝類來說是什么樣子的:

def __post_init__(self):

if type(self.release_date) is str:

self.release_date = dateutil.parser.parse(self.release_date)

if type(self.created) is str:

self.created = dateutil.parser.parse(self.created)

if type(self.edited) is str:

self.edited = dateutil.parser.parse(self.edited)

就是這樣! 我們可以使用 data class 裝飾器在用三分之二的代碼量實現我們的類。

更多好東西

通過使用裝飾器的選項,可以為用例進一步定制 data class,默認選項是:

@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)

init決定是否生成__init__ dunder 方法

repr決定是否生成__repr__ dunder方法

eq對__eq__ dunder 方法也是如此,它決定相等性檢查的行為(your_class_instance == another_instance)

order 實際上創建了四種 dunder 方法,它們確定所有檢查小于,and/or,大于的行為,如果將其設置為 true,則可以對對象列表進行排序。

最后兩個選項確定對象是否可以被哈希化,如果你想使用你的 class 的對象作為字典鍵的話,這是必要的。

python類裝飾器用法實例

本文實例講述了python類裝飾器用法。分享給大家供大家參考。具體如下:

#!coding=utf-8

registry = {}

def register(cls):

registry[cls.__clsid__] = cls

return cls

@register

class Foo(object):

__clsid__ = '123-456'

def bar(self):

pass

print registry

運行結果如下:

{'123-456': }

希望本文所述對大家的Python程序設計有所幫助。

Python 使用類寫裝飾器的小技巧

最近學到了一個有趣的裝飾器寫法,就記錄一下。

裝飾器是一個返回函數的函數。寫一個裝飾器,除了最常見的在函數中定義函數以外,Python還允許使用類來定義一個裝飾器。

1、用類寫裝飾器

下面用常見的寫法實現了一個緩存裝飾器。

def cache(func):

data = {}

def wrapper(*args, **kwargs):

key = f'{func.__name__}-{str(args)}-{str(kwargs)})'

if key in data:

result = data.get(key)

print('cached')

else:

result = func(*args, **kwargs)

data[key] = result

print('calculated')

return result

return wrapper

看看緩存的效果。

@cache

def rectangle_area(length, width):

return length * width

rectangle_area(2, 3)

# calculated

# 6

rectangle_area(2, 3)

# cached

# 6

裝飾器的@cache是一個語法糖,相當于func = cache(func),如果這里的cache不是一個函數,而是一個類又會怎樣呢?定義一個類class Cache, 那么調用func = Cache(func)會得到一個對象,這時返回的func其實是Cache的對象。定義__call__方法可以將類的實例變成可調用對象,可以像調用函數一樣調用對象。然后在__call__方法里調用原本的func函數就能實現裝飾器了。所以Cache類也能當作裝飾器使用,并且能以@Cache的形式使用。

接下來把cache函數改寫為Cache類:

class Cache:

def __init__(self, func):

self.func = func

self.data = {}

def __call__(self, *args, **kwargs):

func = self.func

data = self.data

key = f'{func.__name__}-{str(args)}-{str(kwargs)})'

if key in data:

result = data.get(key)

print('cached')

else:

result = func(*args, **kwargs)

data[key] = result

print('calculated')

return result

再看看緩存結果,效果一樣。

@Cache

def rectangle_area(length, width):

return length * width

rectangle_area(2, 3)

# calculated

# 6

rectangle_area(2, 3)

# cached

# 6

2、裝飾類的方法

裝飾器不止能裝飾函數,也經常用來裝飾類的方法,但是我發現用類寫的裝飾器不能直接用在裝飾類的方法上。(有點繞…)

先看看函數寫的裝飾器如何裝飾類的方法。

class Rectangle:

def __init__(self, length, width):

self.length = length

self.width = width

@cache

def area(self):

return self.length * self.width

r = Rectangle(2, 3)

r.area()

# calculated

# 6

r.area()

# cached

# 6

但是如果直接換成Cache類會報錯,這個錯誤的原因是area被裝飾后變成了類的一個屬性,而不是方法。

class Rectangle:

def __init__(self, length, width):

self.length = length

self.width = width

@Cache

def area(self):

return self.length * self.width

r = Rectangle(2, 3)

r.area()

# TypeError: area() missing 1 required positional argument: 'self'

Rectangle.area

# <__main__.Cache object at 0x0000012D8E7A6D30>

r.area

# <__main__.Cache object at 0x0000012D8E7A6D30>

回頭再來看看沒有裝飾器的情況,Python在實例化對象后把函數變成了方法。

class Rectangle:

def __init__(self, length, width):

self.length = length

self.width = width

def area(self):

return self.length * self.width

Rectangle.area

#

r = Rectangle(2, 3)

r.area

#

因此解決辦法很簡單,要用類寫的裝飾器來裝飾類的方法,只需要把可調用對象包裝成函數就行。

# 定義一個簡單的裝飾器,什么也不做,僅僅是把可調用對象包裝成函數

def method(call):

def wrapper(*args, **kwargs):

return call(*args, **kwargs)

return wrapper

class Rectangle:

def __init__(self, length, width):

self.length = length

self.width = width

@method

@Cache

def area(self):

return self.length * self.width

r = Rectangle(2, 3)

r.area()

# calculated

# 6

r.area()

# cached

# 6

或者用@property還能直接把方法變成屬性。

class Rectangle:

def __init__(self, length, width):

self.length = length

self.width = width

@property

@Cache

def area(self):

return self.length * self.width

r = Rectangle(2, 3)

r.area

# calculated

# 6

r.area

# cached

# 6

總結

用類寫裝飾器并非什么特別的技巧,一般情況下確實沒必要這么寫,不過這樣就可以用一些類的特性來寫裝飾器,比如類的繼承,也算是提供了另一種思路吧。

以上就是本次給大家分享的關于java的全部知識點內容總結,大家還可以在下方相關文章里找到相關文章進一步學習,感謝大家的閱讀和支持。

總結

以上是生活随笔為你收集整理的python3.7用法_Python 3.7中dataclass装饰器用法详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。