python 基礎之常用函式eval(),filter(),extend()等
get, getattr, __getattribute__的區別
ref
obj.getattribute(self, name)
在例項訪問屬性的時候無條件被呼叫。如果class中定義了__getattr__(),getattr()也不會被呼叫,除非顯示的呼叫或者沒有訪問到屬性引發AttributeError異常
obj.getattr(self, name)
當一般位置找不到屬性時,會呼叫__getattr__()返回一個值,如果不存在__getattr__()方法則會引發AttributeError異常。
obj.get(self, instance, owner)
descriptor的例項自己訪問自己是不會觸發__get__,而會觸發__call__,只有descriptor作為其它類的屬性才有意義。
類裡面是預設不會提供__get__()方法的
getattr(self, name), setattr(self, name, value),delattr(self, name)
ref
在舊式類中,可以使用__getattr__(self, name), setattr
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def __setattr__(self, name, value):
if name == 'size':
self.width, self.height = value
else:
self.__dict__[ name] = value
def __getattr__(self, name):
if name == 'size':
return self.width, self.height
else:
raise AttributeError
def __delattr__(self, name):
if name == 'size':
del self.__dict__['width']
del self.__dict__['height']
else:
if name in self.__dict__:
del self.__dict__[name]
else:
raise KeyError
注意__dict__方法包含一個字典,字典裡是所有例項的屬性, getattr 只有在訪問不存在的成員時才會被呼叫。如果型別繼承自 object,可以使用__getattribute__ 來攔截所有(包括不存在的成員)的獲取操作, 其也可以攔截對__dict__的訪問,因此__getattribute__ 中不要使用 “return self.dict[name]” 來返回結果,因為在訪問 “self.dict” 時同樣會被 getattribute 攔截,從而造成無限遞迴形成死迴圈。
訪問__getattribute__中與self相關的特性,可以使用超類的__getattribute__(使用super函式)來獲取操作。
class A(object):
def __getattribute__(self, name):
return object.__getattribute__(self, name)
常用函式
eval()
ref
eval(expression[, globals[, locals]])用來執行一個字串表示式,並返回表示式的值。
x = 7
>>> eval( '3 * x' )
21
>>> eval('pow(2,2)')
4
>>> eval('2 + 2')
4
>>> n=81
>>> eval("n + 4")
85
可以把list,tuple,dict和string相互轉化。
a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
b = eval(a)
print b
#[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
指定globals
a=10;
g={'a':4}
print(eval("a+1",g))
# eval中提供了globals引數,這時候eval的作用域就是g指定的這個字典了,也就是外面的a=10被遮蔽掉了,eval是看不見的,所以使用了a為4的值。
指定locals
a=10
b=20
c=30
g={'a':6,'b':8}
t={'b':100,'c':10}
print(eval('a+b+c',g,t))
要確保第一個引數expression滿足表示式的要求,它是可以被解析然後計算的
s="abck"
print(eval(s))## 輸出NameError: name 'abck' is not defined
#當eval剝去了"abck"的外面的引號的時候,它會對它進行解析,然後滿足要求後進行計算,然後它解析到的是abcd,請注意,程式報出的錯誤是NameError,也就是說,當它解析到這個表示式是不可以計算後,它就會查詢它是不是一個變數的名字,如果是一個變數的名字,那麼它會輸出這個變數的內容,否則就會產生這種報錯。
s="abck"
print(eval('s')) ## 輸出abck
s='"sas"'
print(eval(s)) ## 輸出sas
#eval在執行的時候是隻會去除同種型別的引號的,對於單引號和雙引號它是加以區分的
s='["a","b","c"]'
print(eval(s))
a=10
b=20
c=30
s='[a,b,c]'
print(eval(s)) ## [10, 20, 30]
# eval檢查到列表的‘[’‘]’符號時,是會對裡面的元素進行解析的,這裡a、b、c顯然不是具體的資料,便去查詢它們是否是變數名,然後確認是變數名後,用它們的內容替換掉它。
filter()
# filter(function, iterable)
def is_odd(n):
return n % 2 == 1
newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(newlist) ## [1, 3, 5, 7, 9]
import math
def is_sqr(x):
return math.sqrt(x) % 1 == 0
newlist = list(filter(is_sqrt, range(1, 101))) #注意這裡轉成list
print(newlist) ## [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
extend()
該方法沒有返回值,但會在已存在的列表中新增新的列表內容。
list.extend(seq)
num = [1,2]
num.extend([1]*2) ## [1, 2, 1, 1]
append與extend區別:
append命令是將整個物件加在列表末尾;而extend命令是將新物件中的元素逐一加在列表的末尾。
append命令可以新增單個元素,也可以新增可迭代物件;而extend命令只能新增可迭代物件。
List=[]
list.extend([1,2,3])
print(list) ##[1,2,3]
List=[]
list.append([1,2,3])
print(list) ##[[1,2,3]]