一、作用域
(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__定義的屬性僅對當前類實例其作用,對繼承的子類是不起作用的。