isinstance(obj,cls)檢查是否obj是不是類 cls 的對象java
class Foo(object): pass obj = Foo() isinstance(obj, Foo)
issubclass(sub, super)檢查sub類是不是 super 類的派生類 python
class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)
1 什麼是反射程序員
反射的概念是由Smith在1982年首次提出的,主要是指程序能夠訪問、檢測和修改它自己狀態或行爲的一種能力(自省)。這一律唸的提出很快引起了計算機科學領域關於應用反射性的研究。它首先被程序語言的設計領域所採用,並在Lisp和麪向對象方面取得了成績。面試
2 python面向對象中的反射:經過字符串的形式操做對象相關的屬性。python中的一切事物都是對象(均可以使用反射)算法
四個能夠實現自省的函數編程
下列方法適用於類和對象(一切皆對象,類自己也是一個對象)python3.x
def hasattr(*args, **kwargs): # real signature unknown """ Return whether the object has an attribute with the given name. This is done by calling getattr(obj, name) and catching AttributeError. """ pass
def getattr(object, name, default=None): # known special case of getattr """ getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. """ pass
def setattr(x, y, v): # real signature unknown; restored from __doc__ """ Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v'' """ pass
def delattr(x, y): # real signature unknown; restored from __doc__ """ Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y'' """ pass
class Foo: f = '類的靜態變量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #檢測是否含有某屬性 print(hasattr(obj,'name')) print(hasattr(obj,'say_hi')) #獲取屬性 n=getattr(obj,'name') print(n) func=getattr(obj,'say_hi') func() print(getattr(obj,'aaaaaaaa','不存在啊')) #報錯 #設置屬性 setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #刪除屬性 delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#不存在,則報錯 print(obj.__dict__)
class Foo(object): staticField = "old boy" def __init__(self): self.name = 'wupeiqi' def func(self): return 'func' @staticmethod def bar(): return 'bar' print getattr(Foo, 'staticField') print getattr(Foo, 'func') print getattr(Foo, 'bar')
#!/usr/bin/env python # -*- coding:utf-8 -*- import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2')
改變對象的字符串顯示__str__,__repr__api
自定製格式化字符串__format__app
#_*_coding:utf-8_*_ format_dict={ 'nat':'{obj.name}-{obj.addr}-{obj.type}',#學校名-學校地址-學校類型 'tna':'{obj.type}:{obj.name}:{obj.addr}',#學校類型:學校名:學校地址 'tan':'{obj.type}/{obj.addr}/{obj.name}',#學校類型/學校地址/學校名 } class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __repr__(self): return 'School(%s,%s)' %(self.name,self.addr) def __str__(self): return '(%s,%s)' %(self.name,self.addr) def __format__(self, format_spec): # if format_spec if not format_spec or format_spec not in format_dict: format_spec='nat' fmt=format_dict[format_spec] return fmt.format(obj=self) s1=School('oldboy1','北京','私立') print('from repr: ',repr(s1)) print('from str: ',str(s1)) print(s1) ''' str函數或者print函數--->obj.__str__() repr或者交互式解釋器--->obj.__repr__() 若是__str__沒有被定義,那麼就會使用__repr__來代替輸出 注意:這倆方法的返回值必須是字符串,不然拋出異常 ''' print(format(s1,'nat')) print(format(s1,'tna')) print(format(s1,'tan')) print(format(s1,'asfdasdffd'))
class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b=B() print('%s'%b) print('%r'%b)
析構方法,當對象在內存中被釋放時,自動觸發執行。dom
注:此方法通常無須定義,由於Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,由於此工做都是交給Python解釋器來執行,因此,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。
class Foo: def __del__(self): print('執行我啦') f1=Foo() del f1 print('------->') #輸出結果 執行我啦 ------->
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]時,我執行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key時,我執行') self.__dict__.pop(item) f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)
class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A, *args, **kwargs) a = A() print(a.x)
class Singleton: def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): cls._instance = object.__new__(cls, *args, **kw) return cls._instance one = Singleton() two = Singleton() two.a = 3 print(one.a) # 3 # one和two徹底相同,能夠用id(), ==, is檢測 print(id(one)) # 29097904 print(id(two)) # 29097904 print(one == two) # True print(one is two) 單例模式
對象後面加括號,觸發執行。
注:構造方法的執行是由建立對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 執行 __init__ obj() # 執行 __call__
class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a))
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True a = A() b = A() print(a == b)
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['紅心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck))
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['紅心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] def __setitem__(self, key, value): self._cards[key] = value deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck)) from random import shuffle shuffle(deck) print(deck[:5])
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name == other.name and self.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('egon',i,'male')) print(p_lst) print(set(p_lst))
# class A: # pass # class B(A): # pass # 多繼承 # class File: # def open(self): # pass # def close(self): # pass # class DB: # def connect(self): # pass # def disconnect(self): # pass # class C(File,DB): # pass # 多繼承: # 假設一個類,既擁有A類的功能,又擁有B類的功能,就會用到多繼承。 # 多繼承以後,寫在父類位置上的類都被稱爲我子類的父類了。 # class A: # def func(self): # print('A') # class B: # def func(self): # print('B') # class C(A,B): # pass # c = C() # c.func() # PY2.7 / PY3.X 新式類和經典類 - 多繼承 # 多繼承在新式類中的繼承規則 # 在經典類中的繼承規則 class A: def func(self): print('A') class B(A): pass # def func(self): # print('B') class C(A): pass # def func(self): # print('C') class D(B,C): pass # def func(self): # print('D') # d = D() # d.func() class A: def func(self): print('A') class B(A): pass # def func(self): # print('B') class C(A): pass def func(self): print('C') class D(B): pass # def func(self): # print('D') class E(C): pass def func(self): print('E') class F(D,E): pass # def func(self): # print('F') print(F.mro()) # 類的多繼承 # python3.x # 全部的類都是新式類 # 全部的新式類都默認繼承object類 # object類是全部python3中類的父類/基類 # 這個類中提供了不少基礎的方法 # 使得即便咱們建立一個類什麼也不作,仍然可使得這個類具有python中類的一些基本功能 # 多繼承 # 全部的新式類在多繼承尋找名字的過程當中都遵循廣度優先 # 橫向是廣度,縱向是深度 # 廣度優先 :所謂的廣度優先並非一味的橫向運動, # 而是在找尋下一個點的時候,要思考這個點在後面的其餘點還有沒有直接找到他的可能性 # 若是有,那麼咱們如今要先放棄這個點,先橫向尋找 # 若是後面已經沒有辦法走到這個點了,那應該縱向先尋找以後再往橫向走 # mro方法: # 在新式類中給咱們提供了一個mro方法,讓咱們可以查看多個類之間的繼承順序 # 在多繼承中的super # super遵循的永遠是mro順序 # class A: # def func(self): # print('A') # class B(A): # def func(self): # super().func() # print('B') # class C(A): # def func(self): # super().func() # print('C') # class D(B,C): # def func(self): # super().func() # print('D') # # d = D() # d.func() # python2.7 # 繼承object : # 經典類 # class A:pass # 新式類並存 # class A(object):pass # 多繼承 # 新式類的繼承特色仍然是廣度優先 # 經典類的繼承特色 就是 深度優先 # 在尋找類中的方法的時候,老是從最左邊的一條分支開始,一直走到底,再依次向右走 # 經典類是沒有mro方法的 # super(子類名,子類對象).方法名() # 在py2.7中使用super是必需要傳遞子類名和子類對象這兩個參數的
class Pay:pass class Ali(Pay): def pay(self,name,money): # 調用支付寶提供給個人一個方法 # 連接支付寶 # 調用付款方法 # 獲得返回值 # 顯示支付是否成功 pass class Wechat(Pay): def pay(self,name,money): # 調用支付寶提供給個人一個方法 # 連接支付寶 # 調用付款方法 # 獲得返回值 # 顯示支付是否成功 pass ali_obj = Wechat() # java # def pay(str name,Pay payobj,int money): # payobj.pay(name,money) # python def pay(name,payobj,money): payobj.pay(name,money) # pay('alex',ali_obj,100) # python是沒有多態 # python當中到處是多態 # 多態 : 利用面向對象的繼承 實現的一種傳參的兼容方式
# class Goods: # discount = 0.7 # __discount = 0.8 # 對外不可用了 # # def __init__(self): # # pass # def func(self): # pass # __雙下方法__ __魔術方法__ # __變量名 私有的,私有的都不能在類的外部直接訪問 # 是由於在類的內部對於__名字的值有一個特殊的變形 _類名__名字 # print(Goods.discount) # print(Goods.__discount) # print(Goods._Goods__discount) # class Goods: # def __init__(self,o_price): # self.__price = o_price # def get_price(self): # return self.__price # apple = Goods(5) # print(apple.get_price()) # 私有的對象屬性 # 私有的靜態屬性 # 定義私有 : # 是爲了保護變量不被隨意修改,爲了某個方法只在類的內部被調用 # 私有的方法和屬性不能被子類繼承 # 在類中調用的全部的私有名字都是直接找本類中的私有名字 # 定義私有的方法 # class Login: # def __init__(self,name,pwd): # self.name = name # self.pwd = self.__get_pwd(pwd) # 12345 # # def __get_pwd(self,pwd): # # 一系列算法 # return pwd # 繼承 : class Foo: def __init__(self): self.__func() # _Foo__func def __func(self): # _Foo__func print('in Foo') class Son(Foo): pass # def __func(self): # print('in Son') def myfunc(self): self.__func() # _Son__func() obj = Son() obj.myfunc() # 私有 # 私有的靜態屬性 # 私有的對象屬性 # 私有的方法 # 定義私有 : # 變量 # 是爲了保護變量不被隨意修改 # 方法 # 爲了某個方法只在類的內部被調用 # 私有的方法和屬性不能被子類繼承 # 在類中調用的全部的私有名字都是直接找本類中的私有名字
# 單繼承 # 多繼承 3個類 # 封裝 __名字 變形機制/基礎用法 # 68個內置函數 # 55個 # @property # @classmethod # @staticmethod # from math import pi # class Circle: # def __init__(self,r): # self.r = r # @property # 用來裝飾一個方法,將這個方法假裝成一個屬性 # def area(self): # return pi * self.r**2 # @property # def perimeter(self): # return 2* pi * self.r # # c1 = Circle(10) # # 圓形對象 計算面積 動詞 # # 的面積 名詞 - 屬性 # print(c1.r) # print(c1.area) #---> c1.area() # print(c1.perimeter) #---> c1.perimeter() # class Goods: # def __init__(self,price): # self.__price = price # # def get_price(self): # return self.__price # @property # def price(self): # return self.__price # # apple = Goods(5) # apple.get_price() # apple.price # property 用來裝飾一個方法,將這個方法假裝成一個屬性 # 有一些方法,它自己的返回值應該做爲這個對象的屬性 # 當咱們想給一個私有的變量設置一個查看方法的時候 # property只是從邏輯的合理性和程序的美觀度上面作出了一些修正 # class Goods: # __discount = 0.8 # def __init__(self,price): # self.__price = price # # @property # def price(self): # return self.__price * Goods.__discount # # @classmethod # def change_discount(cls,new): # 當前類 Goods # cls.__discount = new # 不須要使用對象調用 # 在傳參數的時候不須要傳類名 # Goods.change_discount(0.7) # apple = Goods(5) # banana = Goods(10) # print(banana.price) # print(apple.price) # Goods.change_discount(0.9) # print(banana.price) # print(apple.price) # 當咱們寫了一個類中的方法,發現並無使用到對象的任何屬性 # 只是用到了類的命名空間中的變量(除了接收self參數的方法) # 你就將這個方法定義成一個被@classmethod裝飾器裝飾的方法 # 這個方法就被稱爲一個類方法 # @staticmethod # 面向對象編程 沒有函數的概念 # class Beginer: # @staticmethod # def login(): # 本質上就是一個函數,也不須要默認的類,self對象 # pass # # Beginer.login() # @property 把一個普通的方法裝飾成屬性 # @classmethod 把一個普通的方法裝飾成類方法, # 調用方式 類名.方法名 # 定義方式 參數 從 self --> cls # @staticmethod 把一個普通的方法裝飾成類中的函數/靜態方法 # 調用方式 類名.方法名 # 定義方式 參數 從self --> 沒有默認必須傳的參數了 # class A:pass # class B(A):pass # b = B() # # print(isinstance(對象,類)) # print(isinstance(b,B)) # print(isinstance(b,A)) # # print(type(b) is B) # print(type(b) is A) # print(issubclass(子類,父類)) # print(issubclass(B,A)) # print(issubclass(A,B))
# name = 'alex' # age = 123 # inp = input('>>>') # 'age' / 'name' # 有些時候,咱們須要經過字符串數據類型的變量名來獲取變量的值 # 幾個做用域須要考慮 # 類中的 getattr(類名,‘變量名’) # 對象中的 getattr('對象名','變量名') # 本文件中的 getattr(sys.modules[__name__],'變量名') # 模塊中的 getattr('模塊名','變量名') # class A: # Country1 = 'China' # Country2 = 'America' # @classmethod # def show_country(cls): # print(cls.Country1) # print(cls.Country2) # print(A.Country) # ret = getattr(A,'Country1') # # print(ret) # print(hasattr(A,'Country1')) # print(hasattr(A,'Co')) # inp = input('>>>') # if hasattr(A,inp): # print(getattr(A,inp)) # print(A.show_country) # ret = getattr(A,'show_country') # ret() # class Student: # def __init__(self,name): # self.name = name # def show_courses(self): # print('查看可選擇的課程') # xiaoming = Student('小明') # print(xiaoming.name) # print(getattr(xiaoming,'name')) # xiaoming.show_courses() # getattr(xiaoming,'show_courses')() import sys # name = 'alex' # age = 123 # print(name) # print(sys.modules[__name__].name) # print(getattr(sys.modules[__name__],'name')) # def login(): # print('login') # # def register(): # print('register') # inp = input('>>>') # getattr(sys.modules[__name__],inp)() # 反射本模塊中的類 # class Student: # pass # # class Mangaer: # pass # # cls = input('>>>') # clas = getattr(sys.modules[__name__],cls) # print(clas()) # import time # # time.time() # # time.localtime() # print(getattr(time,'time')()) # print(getattr(time,'localtime')()) # setattr delattr # class A: # abc = 'aabbcc' # setattr(A,'abc','ccbbaa') # print(A.abc) # delattr(A,'abc')# del A.abc # print(A.abc)
# 學院選課系統 import sys class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher class Student: operate_lst = [('查看可選課程','show_courese'), ('選擇課程','choose_course'), ('查看已選課程','show_selected_course'), ('退出','exit')] def __init__(self,name): self.name = name self.courses = [] def show_courese(self): print('查看可選課程') def choose_course(self): print('選擇課程') def show_selected_course(self): print('查看已選課程') def exit(self): print('退出') class Manager: operate_lst = [('建立課程', 'create_course'), ('建立學生', 'create_student'), ('查看可選課程', 'show_courese'), ('查看學生', 'show_students'), ('查看全部學生以及所選課程', 'show_stu_course'), ('退出', 'exit')] def __init__(self,name): self.name = name def create_course(self): # pickle 內置方法的用法 print('建立課程') def show_courese(self): print('查看可選課程') def create_student(self): print('建立學生') def show_students(self): print('查看全部學生') def show_stu_course(self): print('查看全部學生以及所選課程') def exit(self): print('退出') # 從管理員功能開始開發 # 登陸 # 自動根據你的用戶名和密碼 判斷身份 def login(): usr = input('username :') pwd = input('password :') with open('userinfo') as f: for line in f: user,passwd,identify = line.strip().split('|') if usr == user and passwd == pwd: print('登陸成功') return {'usr':usr,'identify':identify} else: print('登陸失敗') return {'usr': usr, 'identify': None} ret = login() if ret['identify']: cls = getattr(sys.modules[__name__],ret['identify']) obj = cls(ret['usr']) for index,i in enumerate(cls.operate_lst,1): print(index,i[0]) ind = int(input('num >>')) operate = cls.operate_lst[ind-1][1] getattr(obj,operate)()
# 什麼是模塊? # 一組功能的集合 # import my_module # 只要是py文件均可以稱爲模塊 # 模塊的名字 必須符合變量的命名規範 # 導入一個模塊至關於執行了這個py文件 # print(my_module.name) # my_module.read1() # 模塊重命名 # import my_module as m # print(m.name) # m.read1() # import sys as s # print(s.path) # 導入多個模塊 # import os,sys # import os as o,sys as s # 三種模塊 # 內置模塊 # 第三方模塊 # 自定義模塊 # from import # from my_module import name as n,read1 as r # print(n) # r() # 模塊重命名 # 導入多個名字 # * # from my_module import * # print(name) # read1() # 模塊搜索路徑, # 一個模塊能不能被導入 就看這個模塊所在的目錄是否在sys.path中 # import my_module # import sys # print(sys.path) # 若是被執行的文件和要導入的文件在同級目錄下,能夠直接導入 # 若是被執行的文件和要導入的文件不在同級目錄下 # 須要咱們本身修改sys.path # import sys # sys.path.append(r'D:\myproject\py23\day7\glance\api') # import policy # policy.get() # if __name__ == '__main__': import my_module # __name__是一個變量 # 當__name__所在的文件被直接執行的時候,那麼__name__ == '__main__' # 當__name__所在的文件被導入的時候,那麼__name__ ==‘模塊的名字’ # if __name__ == '__main__': # print('是你但願在被直接執行的時候纔會走的邏輯') # import calculator # ret = calculator.cal('1-2+3') # print(ret) # 包 # import sys # print(sys.path) # import # import glance.api.policy as policy # policy.get() # from import # from glance.api import policy # policy.get() # from glance.api.policy import get # get()
def cal(s): eval(s) if __name__ == '__main__': inp = input('>>>') print(cal(inp))