python作用域、動態添加屬性和方法、__slots__的作用

一、作用域

(1) LEGB 規則

python使用LEGB的順序來查找一個符號對應的對象。LEGB 即:
局部 閉包 全局 內建
locals --> enclosing function --> globals --> builtins

# 1. locals當前所有命名空間(如函數、模塊),函數的參數也屬於命名空間內的變量
# 2. enclosing 外部嵌套函數的命名空間(閉包中常見)
def test1()
	a = 10 
	def test2():
		# a 位於外部嵌套函數的命名空間
		print(a)
# 3. globals 全局變量
a = 2
def test():
	global a # 通過global指令來申明全局變量
	a = 2    # 修改全局變量,而不是創建一個局部變量
# 4. builtins 內建模塊的命名空間

下面通過例子可以清楚的瞭解這些變量在什麼時候會被調用:

num = 100  # globals  全局變量,如果內有則在內建中查找,找不到就報錯。
def test1()
	num = 200     # enclosing function 閉包
	def test2():
		num = 300  # 先查找局部變量locals,如果沒有局部變量,那就查找閉包
		print(num)
	return test2
test1()
# 從上面可以看到變量是怎麼的順序進行查找的。查看內建用:dir(__builtin__)

二、動態添加屬性和方法

(1) python 是動態語言
也就是說動態語言在運行的過程中可以改變其結構。那麼相反靜態語言就是在運行過程中不能修改其結構。

(2) 動態的添加屬性

# 定義一個類
class Person(object):
	def __init(self, Name, Age):
		self.name = Name
		self.age = Age
# 創建對象
p = Person('小明', '20')
print(p.name)
print(p.age)
# 給對象p 添加一個屬性
p.addr = "上海"
print(p.addr)

f = Person("小李"'30')
print(f.addr) # 此時會報錯,對象沒有該屬性,因爲這個對象是新創建的,該屬性addr不存在。那麼爲了解決這類問題,就需要給類添加屬性。

# 給類添加屬性
Person.num = 100
print(p.num)
print(f.num) 

(3) 動態的添加方法

"""給對象添加方法要藉助函數types.MethodType(方法名,對象名)"""
import types
對象名.XXX = types.MethodType(方法名,對象名)
# 調用
對象名.XXX()     
class Person(object):
	def __init__(self, newName):
		self.name = newName
p1 = Person("p1")
def eat(self):
	print("%s 正在吃飯......"%self.name)

# 給對象p1添加方法eat()
import types
p1.run = types.MethodType(eat, p1)
# 調用添加的方法
p1.run()

總結:1、 給對象添加屬性: 對象.屬性名 = “ 具體的值”
2、 給類添加屬性: 類名.屬性名 = “具體的值”
3、 給對象添加方法:對象名.XXX = types.MethodType(方法名,對象名)

三、__slots__變量

如果現在有一個需求,讓我們限制添加實例的屬性,如:只允許對上面的Person()實例對象添加兩個屬性,name和age,爲了達到這種目的Python採用__slots__變量進行限制。

# 怎麼限制屬性
class Person(obect):
	__slots__ = ("name", "age")

# 創建對象
p = Person()
p.name = "小明"
p.age = 20
p.score = 98 # 這裏就會報錯,因爲該類的實例對象只能添加name和age兩個屬性。

注意: 使用__slots__變量時需要注意,__slots__定義的屬性僅對當前類實例其作用,對繼承的子類是不起作用的。

發佈了32 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章