網站首頁 編程語言 正文
一、類和對象
Python屬于動態類型的語言,而動態語言和靜態語言最大的不同,就是函數和類的定義,不是編譯時創建的,而是運行時動態創建的,比方說我們要定義一個 Person
的class,就寫一個 Person.py
模塊:
# -*- coding: utf-8 -*- # 文件名 : Person.py class Person(object): def say(self, s='元類'): print('今日學習:%s' % s) if __name__ == '__main__': p = Person() p.say()
當Python解釋器載入 Person
模塊時,就會依次執行該模塊的所有語句,執行結果就是動態創建出一個 Person
的class對象,測試如下,(注意,是引入一個Person.py腳本)
# 文件名 :測試.py # 引入模塊,需要模塊的路徑 from Person import Person # 創建一個Person類的實例 p = Person() p.say('Python中的元類') # 調用say方法 # 今日學習:Python中的元類 print(type(p)) # 把實例 p 的類型打印出來 # <class 'say.Person'> print(type(Person)) # Person 類的類型打印出來 # <class 'type'>
這里是用來 type()
函數,可以查看一個類型或變量,的類型, Person
是一個class,它的類型就是 type
,而 p
是一個實例,它的類型就是class Person
。
二、type類
我們說class的定義是運行時動態創建的,而創建class的方法就是使用 type()
函數
type()
函數既可以返回一個對象的類型,又可以創建出新的類型,比如,我們可以通過 type()
函數創建出Person 類,而無需通過 class Person(object)...
的定義,此時type的第二種用法,我們只要type傳object是可以返回該對象類型的,但是當我們的type存在三位參數存在時
# type 類 class type(object): """ type(object_or_name, bases, dict) type(object) -> the object's type type(name, bases, dict) -> a new type """ #參數介紹 """ type(object_or_name, bases, dict) object-or-name -- 對象或類的名稱。 bases -- 基類的元組。 dict -- 字典,類內定義的命名空間變量。 """ # 返回新的類型對象。
# -*- coding: utf-8 -*- def fun(self, s): print('hello'+s) Hello = type('hello', (object,), dict(func=fun)) if __name__ == '__main__': h = Hello() h.func(' word') # hello word print(type(h)) # <class '__main__.hello'> print(type(Hello)) # <class 'type'>
我們通過 type()
函數創建的類和直接寫class是完全一樣的,因為Python解釋器遇到class定義時,僅僅是掃描一下class定義的語法,然后調用 type()
函數創建出class
在正常情況下,我們都用 class Xxx...
來定義類,但是, type()
函數也允許我們動態創建出類來,也就是說,動態語言本身支持運行期動態創建類,這和靜態語言有非常大的不同,要在靜態語言運行期創建類,必須構造源代碼字符串再調用編譯器,或者借助一些工具生成字節碼實現,本質上都是動態編譯,會非常復雜
三、元類Metaclass
除了使用 type()
動態創建類以外,要控制類的創建行為,還可以使用metaclass
,也就是元類
當我們定義了類以后,就可以根據這個類創建出實例,所以:先定義類,然后創建實例
但是如果我們想創建出類呢?那就必須根據metaclass創建出類,所以:先定義metaclass
,然后創建類,元類就是用來創建這些類(對象)的,元類就是類的類
我們先看一個簡單的例子,這個metaclass
可以給自定義的類增加一個 add
方法定義 ListMetaclass
,按照默認習慣,metaclass的類名總是以Metaclass結尾,以便清楚地表示這是一個metaclas。
四、自定義一個元類
class UpperMetaclass(type): def __new__(mcs, class_name, class_parents, class_attrs): new_attrs = {} for name, value in class_attrs.items(): if not name.startswith('__'): # 判斷是否為非私有屬性 new_attrs[name.upper()] = value # 直接調用type 來創建一個類 return type.__new__(mcs, class_name, class_parents, class_attrs) # 測試 class Emp(object, metaclass=UpperMetaclass): name = '張三' acl = 500 if __name__ == '__main__': print(hasattr(Emp, 'name')) # 判斷Emp中是否有名字為name print(hasattr(Emp, 'NAME')) # 判斷Emp中是否有名字為NAME
原文鏈接:https://aweia.blog.csdn.net/article/details/125622997
相關推薦
- 2022-09-06 python?共現矩陣的實現代碼_python
- 2022-05-26 為Jenkins創建定時構建任務_相關技巧
- 2022-06-02 基于Redis6.2.6版本部署Redis?Cluster集群的問題_Redis
- 2022-11-06 Android實現圓形圖片小工具_Android
- 2021-12-15 使用Redis實現令牌桶算法原理解析_Redis
- 2022-10-19 Docker鏡像與容器的導入導出以及常用命令總結_docker
- 2022-04-03 Python?webargs?模塊的簡單使用_python
- 2022-09-26 nodemon安裝在開發環境(非全局安裝)報錯解決【兩種方式】
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支