自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何禁止 Python 子類(lèi)覆蓋父類(lèi)方法?

開(kāi)發(fā) 后端
當(dāng)實(shí)現(xiàn)我們自己的父類(lèi)Animal的時(shí)候,由于meta.has_base為 False,所以不會(huì)觸發(fā)檢查邏輯。但當(dāng)我們基于Animal實(shí)現(xiàn)Dog子類(lèi)的時(shí)候,由于meta.has_base是True,所以進(jìn)入檢查邏輯。Dog的所有方法名都在attrs參數(shù)里面。循環(huán)檢查每一個(gè)方法名是否在禁止的列表中,如果在,就拋出異常。如果不在,就繼續(xù)后面的創(chuàng)建過(guò)程。

[[428429]]

在昨天的文章里面,我們講到了,當(dāng)子類(lèi)試圖覆蓋父類(lèi)的時(shí)候,可以通過(guò)類(lèi)型標(biāo)注來(lái)發(fā)出警告。今天,我們來(lái)講講如何直接禁止覆蓋。

Python 原生是沒(méi)有提供禁止子類(lèi)覆蓋父類(lèi)的方法的功能,因此我們需要自己來(lái)實(shí)現(xiàn)。

先來(lái)看一下實(shí)現(xiàn)效果:

在這段代碼里面,我們禁止子類(lèi)覆蓋父類(lèi)的dead()和eat()方法,但不禁止move方法。所以,當(dāng)我們?cè)谧宇?lèi)Dog里面嘗試覆蓋父類(lèi)中的dead()時(shí),程序就報(bào)錯(cuò)了。具體要覆蓋哪些方法,可以在定義類(lèi)的時(shí)候指定,傳入的參數(shù)metaclass=protect('方法1', '方法2', '方法3', ...)就可以了。

那么這個(gè)protect函數(shù)是個(gè)什么東西呢?我們來(lái)看看它的代碼:

  1. def protect(*protected): 
  2.     """Returns a metaclass that protects all attributes given as strings""" 
  3.     class Protect(type): 
  4.         has_base = False 
  5.         def __new__(meta, name, bases, attrs): 
  6.             if meta.has_base: 
  7.                 for attribute in attrs: 
  8.                     if attribute in protected: 
  9.                         raise AttributeError('Overriding of attribute "%s" not allowed.'%attribute) 
  10.             meta.has_base = True 
  11.             klass = super().__new__(meta, name, bases, attrs) 
  12.             return klass 
  13.     return Protect 

這里,用到了 Python 的元類(lèi)。如果大家對(duì)元類(lèi)有興趣,可以看9.13 使用元類(lèi)控制實(shí)例的創(chuàng)建 — python3-cookbook 3.0.0 文檔[1]。簡(jiǎn)單的來(lái)說(shuō),元類(lèi)用來(lái)定義類(lèi)的創(chuàng)建行為。它一般的格式為:

  1. class 類(lèi)名(metaclass=另一個(gè)類(lèi)): 
  2.    ... 

而大家看我們用來(lái)禁止重試的這個(gè)函數(shù)protect,它返回的就是一個(gè)Protect類(lèi)。這個(gè)類(lèi)繼承于type對(duì)象。

Protect類(lèi)有一個(gè)__new__方法,這個(gè)方法會(huì)在使用了元類(lèi)的所有子類(lèi)的__init__之前被調(diào)用。在__new__里面,我們拿到了子類(lèi)要定義的方法,并且檢查他們是不是在我們傳給protect的列表里面。如果在,說(shuō)明這個(gè)方法不能被覆蓋。

當(dāng)實(shí)現(xiàn)我們自己的父類(lèi)Animal的時(shí)候,由于meta.has_base為 False,所以不會(huì)觸發(fā)檢查邏輯。但當(dāng)我們基于Animal實(shí)現(xiàn)Dog子類(lèi)的時(shí)候,由于meta.has_base是True,所以進(jìn)入檢查邏輯。Dog的所有方法名都在attrs參數(shù)里面。循環(huán)檢查每一個(gè)方法名是否在禁止的列表中,如果在,就拋出異常。如果不在,就繼續(xù)后面的創(chuàng)建過(guò)程。

元類(lèi)在理解上可能比較困難。如果大家無(wú)法理解上面這一段也沒(méi)有關(guān)系,直接用就是了。

參考文獻(xiàn)

[1] 9.13 使用元類(lèi)控制實(shí)例的創(chuàng)建 — python3-cookbook 3.0.0 文檔: https://python3-cookbook.readthedocs.io/zh_CN/latest/c09/p13_using_mataclass_to_control_instance_creation.html

本文轉(zhuǎn)載自微信公眾號(hào)「未聞Code」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系未聞Code公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 未聞Code
相關(guān)推薦

2024-11-14 10:00:00

Python繼承

2021-10-11 20:02:49

Python父類(lèi)方法

2009-12-16 09:43:35

Ruby父類(lèi)Objec

2009-08-21 14:22:22

C# new和over

2009-09-09 11:28:40

Scala類(lèi)

2023-08-08 08:01:52

Java程序變量

2010-03-18 14:16:52

Java Thread

2020-12-17 08:05:27

JavaSuper用法

2021-04-21 10:01:53

Python類(lèi)方法靜態(tài)方法

2023-12-05 16:01:12

模板方法設(shè)計(jì)模式算法結(jié)構(gòu)

2012-04-10 11:07:41

Java

2009-06-16 10:20:05

多繼承C#

2014-12-29 10:19:01

Java

2019-12-27 15:05:51

Python類(lèi)方法裝飾器

2021-05-21 09:01:56

Python繼承多態(tài)

2016-03-29 10:39:46

iOS函數(shù)初始化

2020-05-26 08:52:36

Java JVM多態(tài)

2010-08-26 15:24:04

DHCP服務(wù)功能

2010-07-22 11:06:31

禁止Telnet 23

2009-12-10 13:37:16

PHP parent
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)