導航:首頁 > 編程語言 > Python如何實現面相切面

Python如何實現面相切面

發布時間:2022-04-29 10:38:56

python是面向什麼的高級語言

面相對象、解釋型。

Python支持多種編程范型,包括函數式、指令式、反射式、結構化和面向對象編程。它擁有動態類型系統和垃圾回收功能,能夠自動管理內存使用,並且其本身擁有一個巨大而廣泛的標准庫。它的語言結構以及面向對象的方法旨在幫助程序員為小型的和大型的項目編寫清晰的、合乎邏輯的代碼。

吉多·范羅蘇姆於1980年代後期開始研發Python,它是作為ABC語言的後繼者,也可以視之為使用叫做的M-表達式的一種傳統中綴表示法的LISP方言。

吉多·范羅蘇姆於1991年首次發布 Python 0.9.0。Python2.0於2000 年發布並引入了新功能。Python3.0於2008年發布,是該語言的主要修訂版,並非完全向後兼容。 Python2於2020年隨2.7.18版停止使用。

Python的設計哲學強調代碼的可讀性和簡潔的語法,尤其是使用空格縮進劃分代碼塊。相比於C或java,Python讓開發者能夠用更少的代碼表達想法。

Python解釋器本身幾乎可以在所有的操作系統中運行。Python的官方解釋器CPython是用C語言編寫的,它是一個由社群驅動的自由軟體,目前由Python軟體基金會管理。

特徵

Python是多范型編程語言。它完全支持結構化編程和面向對象編程,還有很多特徵支持函數式編程和元編程比如元對象協議(元類和魔術方法)。

通過擴展還可以支持很多范型,包括面向切面編程、契約式設計和邏輯編程。

Python使用動態類型,在內存管理上採用引用計數和環檢測相結合的垃圾收集器。它的特徵還有動態名字解析(後期綁定),即在程序執行期間綁定方法和變數的名字。

Python對遵循LISP傳統的函數式編程提供了有限的支持,它提供了map、filter和rece函數;列表推導式、字典、集合和生成器表達式。

⑵ 用python如何實現啊

from random import randint



class Shengfen(object):

def __init__(self, sname):

self.sname = sname

def shengfen(self):

print(self.sname)

class Dijishi(Shengfen):

def __init__(self, sname, dname):

Shengfen.__init__(self, sname)

self.dname = dname

self.money = 10000 #現有錢數

self.number = 0 #商品數量

self.jycs = 0 #交易次數

def attach_g(self): #聯系供應商

self.money -= 100

self.number += 1

if self.number >= 4:

self.xiaoshou() #庫存積攢到4件時,開始銷售該商品

print("現有錢數:" + str(self.money))

print("現有商品數量:" + str(self.number))

def xiaoshou(self): #銷售該商品

if self.jycs < 4: #交易次數小於4次,繼續交易

self.money += 110

self.number -= 1

self.jycs += 1

else: #交易次數大於4次,又百分之50的幾率退貨

if randint(1,2) == 1: #用randint函數創建1/2概率

self.money += 110

self.number -= 1

else:

self.tuihuo()

def tuihuo(self):

self.money -= 30 #退貨一件,相當於虧了30元

print("退貨一件")

class Gebishi(Shengfen):

def __init__(self, sname, gname):

Shengfen.__init__(self, sname)

self.gname = gname

if __name__ == "__main__":

count = 9 #交易次數

Qinshihuang = Dijishi('Guangdong', 'Guangzhou')

Liubang = Gebishi('Guangdong', 'Foshan')

Hanxin = Gebishi('Guangdong', 'Foshan')

for i in range(count):

Qinshihuang.attach_g()

大致按照要求來寫了一下,可能有些地方還有問題,如果有的話,你留言一下,我再幫你改吧

⑶ python是面向對象還是面向過程

面向過程和面對對象是一種編程思想,不能說某某語言是不是面對對象或是面向過程,而是某某語言是否支持面對對象或面向過程。回歸主題,python可以支持面對對象,但也可以支持面向過程,即使不支持面向對象的語言,比如c語言,也可以用面對對象的思想寫程序。你可以理解面對對象為「模塊化」,恰巧python可以做到這一點,自己編寫的函數文件可以用import引用模塊,即使不使用class定義類,也可以實現面對對象的思想。

⑷ 如何設計插件式結構的程序,兼談Python語言

為了擴充軟體的功能,通常我們會把軟體設計成插件式結構。Python這樣的動態語言天生就支持插件式編程。與C++相比,Python已經定義好模塊的介面,想要載入一個插件,一個__import__()就能很輕松地搞定。不需要特定的底層知識。而且與C++等靜態語言相比,Python的插件式結構更顯靈活。因為插件載入後,可以利用Python語言的動態性,充分地修改核心的邏輯。
簡單地說一個__import__()可能不大清楚。現在就來看一個最簡單的插件式結構程序。它會掃描plugins文件夾下的所有.py文件。然後把它們載入。
#-*- encoding: utf-8 -*-#main1.pyimport osclass Platform:
def __init__(self):
self.loadPlugins()

def sayHello(self, from_):
print "hello from %s." % from_

def loadPlugins(self):
for filename in os.listdir("plugins"):
if not filename.endswith(".py") or filename.startswith("_"):
continue
self.runPlugin(filename)

def runPlugin(self, filename):
pluginName=os.path.splitext(filename)[0]
plugin=__import__("plugins."+pluginName, fromlist=[pluginName])
#Errors may be occured. Handle it yourself.
plugin.run(self)if __name__=="__main__":
platform=Platform()

然後在plugins子目錄裡面放入兩個文件:
#plugins1.pydef run(platform):
platform.sayHello("plugin1")#plugins2.pydef run(platform):
platform.sayHello("plugin2")

再創建一個空的__init__.py在plugins文件夾裡面。從package裡面導入模塊的時候,Python要求一個__init__.py。
運行main1.py,看一下運行的結果。首先是列印一下文件夾結構方便大家理解:
h:\projects\workon\testplugins>tree /f /a
卷 Data 的文件夾 PATH 列表
卷序列號為 ****-****
H:.
| main1.py
|
\---plugins
plugin1.py
plugin2.py
__init__.py

h:\projects\workon\testplugins>main1.py
hello from plugin1.
hello from plugin2.

一般地,載入插件前要首先掃描插件,然後依次載入並運行插件。我們上面的示常式序main1.py也是如此,分為兩個函數。第一個loadPlugins()掃描插件。它把plugins目錄下面所有.py的文件除了__init__.py都當成插件。runPlugin()載入並運行插件。其中兩個關鍵:使用__import__()函數把插件當成模塊導入,它要求所有的插件都定義一個run()函數。各種語言實現的插件式結構其實也基本上分為這兩個步驟。所不同的是,Python語言實現起來更加的簡潔。
或許聽起來還有點玄奧。詳細地說一下__import__()。它和常見的import語句很相似,只不過換成函數形式並且返回模塊以供調用。import mole相當於__import__("mole"),from mole import func相當於__import__("mole", fromlist=["func"]),不過與想像有點不同,import package.mole相當於__import__("package.mole", fromlist=["mole"])。
如何調用插件一般有個約定。像我們這里就約定每個插件都實現一個run()。有時候還可以約定實現一個類,並且要求這個類實現某個管理介面,以方便核心隨時啟動、停止插件。要求所有的插件都有這幾個介面方法:
#interfaces.pyclass Plugin:
def setPlatform(self, platform):
self.platform=platform

def start(self):
pass

def stop(self):
pass

想要運行這個插件,我們的runPlugin()要改一改,另外增加一個shutdown()來停止插件:
class Platform:
def __init__(self):
self.plugins=[]
self.loadPlugins()

def sayHello(self, from_):
print "hello from %s." % from_

def loadPlugins(self):
for filename in os.listdir("plugins"):
if not filename.endswith(".py") or filename.startswith("_"):
continue
self.runPlugin(filename)

def runPlugin(self, filename):
pluginName=os.path.splitext(filename)[0]
plugin=__import__("plugins."+pluginName, fromlist=[pluginName])
clazz=plugin.getPluginClass()
o=clazz()
o.setPlatform(self)
o.start()
self.plugins.append(o)

def shutdown(self):
for o in self.plugins:
o.stop()
o.setPlatform(None)
self.plugins=[]if __name__=="__main__":
platform=Platform()
platform.shutdown()

插件改成這樣:
#plugins1.pyclass Plugin1:
def setPlatform(self, platform):
self.platform=platform

def start(self):
self.platform.sayHello("plugin1")

def stop(self):
self.platform.sayGoodbye("plugin1")def getPluginClass():
return Plugin1#plugins2.pydef sayGoodbye(self, from_):
print "goodbye from %s." % from_class Plugin2:
def setPlatform(self, platform):
self.platform=platform
if platform is not None:
platform.__class__.sayGoodbye=sayGoodbye

def start(self):
self.platform.sayHello("plugin2")

def stop(self):
self.platform.sayGoodbye("plugin2")def getPluginClass():
return Plugin2

運行結果:
h:\projects\workon\testplugins>main.py
hello from plugin1.
hello from plugin2.
goodbye from plugin1.
goodbye from plugin2.

詳細觀察的朋友們可能會發現,上面的main.py,plugin1.py, plugin2.py幹了好幾件令人驚奇的事。
首先,plugin1.py和plugin2.py裡面的插件類並沒有繼承自interfaces.Plugin,而platform仍然可以直接調用它們的start()和stop()方法。這件事在Java、C++裡面可能是件麻煩的事情,但是在Python裡面卻是件稀疏平常的事,彷彿吃飯喝水一般正常。事實上,這正是Python鼓勵的約定編程。Python的文件介面協議就只規定了read(), write(), close()少數幾個方法。多數以文件作為參數的函數都可以傳入自定義的文件對象,只要實現其中一兩個方法就行了,而不必實現一個什麼FileInterface。如果那樣的話,需要實現的函數就多了,可能要有十幾個。
再仔細看下來,getPluginClass()可以把類型當成值返回。其實不止是類型,Python的函數、模塊都可以被當成普通的對象使用。從類型生成一個實例也很簡單,直接調用clazz()就創建一個對象。不僅如此,Python還能夠修改類型。上面的例子我們就演示了如何給Platform增加一個方法。在兩個插件的stop()裡面我們都調用了sayGoodbye(),但是仔細觀察Platform的定義,裡面並沒有定義。原理就在這里:
#plugins2.pydef sayGoodbye(self, from_):
print "goodbye from %s." % from_class Plugin2:
def setPlatform(self, platform):
self.platform=platform
if platform is not None:
platform.__class__.sayGoodbye=sayGoodbye

這里首先通過platform.__class__得到Platform類型,然後Platform.sayGoodbye=sayGoodbye新增了一個方法。使用這種方法,我們可以讓插件任意修改核心的邏輯。這正在文首所說的Python實現插件式結構的靈活性,是靜態語言如C++、Java等無法比擬的。當然,這只是演示,我不大建議使用這種方式,它改變了核心的API,可能會給其它程序員造成困惑。但是可以採用這種方式替換原來的方法,還可以利用「面向切面編程」,增強系統的功能。
接下來我們還要再改進一下載入插件的方法,或者說插件的布署方法。前面我們實現的插件體系主要的缺點是每個插件只能有一個源代碼。如果想附帶一些圖片、聲音數據,又怕它們會和其它的插件沖突。即使不沖突,下載時分成單獨的文件也不方便。最好是把一個插件壓縮成一個文件供下載安裝。
Firefox是一個支持插件的著名軟體。它的插件以.xpi作為擴展名,實際上是一個.zip文件,裡麵包含了javascript代碼、數據文件等很多內容。它會把插件包下載復制並解壓到%APPDATA%\Mozilla\Firefox\Profiles\XXXX.default\extensions裡面,然後調用其中的install.js安裝。與此類似,實用的Python程序也不大可能只有一個源代碼,也要像Firefox那樣支持.zip包格式。
實現一個類似於Firefox那樣的插件布署體系並不會很難,因為Python支持讀寫.zip文件,只要寫幾行代碼來做壓縮與解壓縮就行了。首先要看一下zipfile這個模塊。用它解壓縮的代碼如下:
import zipfile, osdef installPlugin(filename):
with zipfile.ZipFile(filename) as pluginzip:
subdir=os.path.splitext(filename)[0]
topath=os.path.join("plugins", subdir)
pluginzip.extractall(topath)

ZipFile.extractall()是Python 2.6後新增的函數。它直接解壓所有壓縮包內的文件。不過這個函數只能用於受信任的壓縮包。如果壓縮包內包含了以/或者盤符開始的絕對路徑,很有可能會損壞系統。推薦看一下zipfile模塊的說明文檔,事先過濾非法的路徑名。
這里只有解壓縮的一小段代碼,安裝過程的界面交互相關的代碼很多,不可能在這里舉例說明。我覺得UI是非常考驗軟體設計師的部分。常見的軟體會要求用戶到網站上查找並下載插件。而Firefox和KDE提供了一個「組件(部件)管理界面」,用戶可以直接在界面內查找插件,查看它的描述,然後直接點擊安裝。安裝後,我們的程序遍歷插件目錄,載入所有的插件。一般地,軟體還需要向用戶提供插件的啟用、禁用、依賴等功能,甚至可以讓用戶直接在軟體界面上給插件評分,這里就不再詳述了。
有個小技巧,安裝到plugins/subdir下的插件可以通過__file__得到它自己的絕對路徑。如果這個插件帶有圖片、聲音等數據的時候,可以利用這個功能載入它們。比如上面的plugin1.py這個插件,如果它想在啟動的時候播放同目錄的message.wav,可以這樣子:
#plugins1.pyimport osdef alert():
soundFile=os.path.join(os.path.dirname(__file__), "message.wav")
try:
import winsound
winsound.PlaySound(soundFile, winsound.SND_FILENAME)
except (ImportError, RuntimeError):
passclass Plugin1:
def setPlatform(self, platform):
self.platform=platform

def start(self):
self.platform.sayHello("plugin1")
alert()

def stop(self):
self.platform.sayGoodbye("plugin1")def getPluginClass():
return Plugin1

接下來我們再介紹一種Python/Java語言常用的插件管理方式。它不需要事先有一個插件解壓過程,因為Python支持從.zp文件導入模塊,很類似於Java直接從.jar文件載入代碼。所謂安裝,只要簡單地把插件復制到特定的目錄即可,Python代碼自動掃描並從.zip文件內載入代碼。下面是一個最簡單的例子,它和上面的幾個例子一樣,包含一個main.py,這是主程序,一個plugins子目錄,用於存放插件。我們這里只有一個插件,名為plugin1.zip。plugin1.zip有以下兩個文件,其中description.txt保存了插件內的入口函數和插件的名字等信息,而plugin1.py是插件的主要代碼:
description.txt
plugin1.py

其中description.txt的內容是:
[general]name=plugin1description=Just a test code=plugin1.Plugin1

plugin1.py與前面的例子類似,為了省事,我們去掉了stop()方法,它的內容是:
class Plugin1:
def setPlatform(self, platform):
self.platform=platform

def start(self):
self.platform.sayHello("plugin1")

重寫的main.py的內容是:
# -*- coding: utf-8 -*-import os, zipfile, sys, ConfigParserclass Platform:
def __init__(self):
self.loadPlugins()

def sayHello(self, from_):
print "hello from %s." % from_

def loadPlugins(self):
for filename in os.listdir("plugins"):
if not filename.endswith(".zip"):
continue
self.runPlugin(filename)

def runPlugin(self, filename):
pluginPath=os.path.join("plugins", filename)
pluginInfo, plugin = self.getPlugin(pluginPath)
print "loading plugin: %s, description: %s" % \ (pluginInfo["name"], pluginInfo["description"])
plugin.setPlatform(self)
plugin.start()

def getPlugin(self, pluginPath):
pluginzip=zipfile.ZipFile(pluginPath, "r")
description_txt=pluginzip.open("description.txt")
parser=ConfigParser.ConfigParser()
parser.readfp(description_txt)
pluginInfo={}
pluginInfo["name"]=parser.get("general", "name")
pluginInfo["description"]=parser.get("general", "description")
pluginInfo["code"]=parser.get("general", "code")

sys.path.append(pluginPath)
moleName, pluginClassName=pluginInfo["code"].rsplit(".", 1)
mole=__import__(moleName, fromlist=[pluginClassName, ])
pluginClass=getattr(mole, pluginClassName)
plugin=pluginClass()
return pluginInfo, pluginif __name__=="__main__":
platform=Platform()

與前一個例子的主要不同之處是getPlugin()。它首先從.zip文件內讀取描述信息,然後把這個.zip文件添加到sys.path裡面。最後與前面類似地導入模塊並執行。
解壓還是不解壓,兩種方案各有優劣。一般地,把.zip文件解壓到獨立的文件夾內需要一個解壓縮過程,或者是人工解壓,或者是由軟體解壓。解壓後的運行效率會高一些。而直接使用.zip包的話,只需要讓用戶把插件復制到特定的位置即可,但是每次運行的時候都需要在內存裡面解壓縮,效率降低。另外,從.zip文件讀取數據總是比較麻煩。推薦不包含沒有數據文件的時候使用。
閱讀全文

⑸ python裝飾器有什麼用

先來個形象比方

內褲可以用來遮羞,但是到了冬天它沒法為我們防風禦寒,聰明的人們發明了長褲,有了長褲後寶寶再也不冷了,裝飾器就像我們這里說的長褲,在不影響內褲作用的前提下,給我們的身子提供了保暖的功效。

再回到我們的主題

裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。它經常用於有切面需求的場景,比如:插入日誌、性能測試、事務處理、緩存、許可權校驗等場景。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。

先來看一個簡單例子:

def foo():
print('i am foo')

現在有一個新的需求,希望可以記錄下函數的執行日誌,於是在代碼中添加日誌代碼:

def foo():
print('i am foo')
logging.info("foo is running")

bar()、bar2()也有類似的需求,怎麼做?再寫一個logging在bar函數里?這樣就造成大量雷同的代碼,為了減少重復寫代碼,我們可以這樣做,重新定義一個函數:專門處理日誌 ,日誌處理完之後再執行真正的業務代碼

def use_logging(func):
logging.warn("%s is running" % func.__name__)
func()def bar():
print('i am bar')use_logging(bar)

邏輯上不難理解,
但是這樣的話,我們每次都要將一個函數作為參數傳遞給use_logging函數。而且這種方式已經破壞了原有的代碼邏輯結構,之前執行業務邏輯時,執行運行bar(),但是現在不得不改成use_logging(bar)。那麼有沒有更好的方式的呢?當然有,答案就是裝飾器。


簡單裝飾器
def use_logging(func):

def wrapper(*args, **kwargs):
logging.warn("%s is running" % func.__name__)
return func(*args, **kwargs)
return wrapperdef bar():
print('i am bar')bar = use_logging(bar)bar()

函數use_logging就是裝飾器,它把執行真正業務方法的func包裹在函數裡面,看起來像bar被use_logging裝飾了。在這個例子中,函數進入和退出時
,被稱為一個橫切面(Aspect),這種編程方式被稱為面向切面的編程(Aspect-Oriented Programming)。

@符號是裝飾器的語法糖,在定義函數的時候使用,避免再一次賦值操作


def use_logging(func):

def wrapper(*args, **kwargs):
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper@use_loggingdef foo():
print("i am foo")@use_loggingdef bar():
print("i am bar")bar()

如上所示,這樣我們就可以省去bar =
use_logging(bar)這一句了,直接調用bar()即可得到想要的結果。如果我們有其他的類似函數,我們可以繼續調用裝飾器來修飾函數,而不用重復修改函數或者增加新的封裝。這樣,我們就提高了程序的可重復利用性,並增加了程序的可讀性。

裝飾器在Python使用如此方便都要歸因於Python的函數能像普通的對象一樣能作為參數傳遞給其他函數,可以被賦值給其他變數,可以作為返回值,可以被定義在另外一個函數內。


帶參數的裝飾器

裝飾器還有更大的靈活性,例如帶參數的裝飾器:在上面的裝飾器調用中,比如@use_logging,該裝飾器唯一的參數就是執行業務的函數。裝飾器的語法允許我們在調用時,提供其它參數,比如@decorator(a)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。

def use_logging(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "warn":
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper

return decorator@use_logging(level="warn")def foo(name='foo'):
print("i am %s" % name)foo()

上面的use_logging是允許帶參數的裝飾器。它實際上是對原有裝飾器的一個函數封裝,並返回一個裝飾器。我們可以將它理解為一個含有參數的閉包。當我
們使用@use_logging(level="warn")調用的時候,Python能夠發現這一層的封裝,並把參數傳遞到裝飾器的環境中。


類裝飾器

再來看看類裝飾器,相比函數裝飾器,類裝飾器具有靈活度大、高內聚、封裝性等優點。使用類裝飾器還可以依靠類內部的\_\_call\_\_方法,當使用 @ 形式將裝飾器附加到函數上時,就會調用此方法。


class Foo(object):
def __init__(self, func):
self._func = func

def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')

@Foo
def bar():
print ('bar')

bar()

functools.wraps

使用裝飾器極大地復用了代碼,但是他有一個缺點就是原函數的元信息不見了,比如函數的docstring、__name__、參數列表,先看例子:

裝飾器

def logged(func):
def with_logging(*args, **kwargs):
print func.__name__ + " was called"
return func(*args, **kwargs)
return with_logging

函數

@loggeddef f(x):
"""does some math"""
return x + x * x

該函數完成等價於:


def f(x):
"""does some math"""
return x + x * xf = logged(f)

不難發現,函數f被with_logging取代了,當然它的docstring,__name__就是變成了with_logging函數的信息了。

print f.__name__ # prints 'with_logging'print f.__doc__ # prints None

這個問題就比較嚴重的,好在我們有functools.wraps,wraps本身也是一個裝飾器,它能把原函數的元信息拷貝到裝飾器函數中,這使得裝飾器函數也有和原函數一樣的元信息了。

from functools import wrapsdef logged(func):
@wraps(func)
def with_logging(*args, **kwargs):
print func.__name__ + " was called"
return func(*args, **kwargs)
return with_logging@loggeddef f(x):
"""does some math"""
return x + x * xprint f.__name__ # prints 'f'print f.__doc__ # prints 'does some math'

內置裝飾器

@staticmathod、@classmethod、@property

裝飾器的順序
@a@b@cdef f ():

等效於


f = a(b(c(f)))

⑹ Python如何工作

Python的特色
簡單
Python是一種代表簡單主義思想的語言。閱讀一個良好的Python程序就感覺像是在讀英語一樣,盡管這個英語的要求非常嚴格!Python的這種偽代碼本質是它最大的優點之一。它使你能夠專注於解決問題而不是去搞明白語言本身。

易學
就如同你即將看到的一樣,Python極其容易上手。前面已經提到了,Python有極其簡單的語法。

免費、開源
Python是FLOSS(自由/開放源碼軟體)之一。簡單地說,你可以自由地發布這個軟體的拷貝、閱讀它的源代碼、對它做改動、把它的一部分用於新的自由軟體中。FLOSS是基於一個團體分享知識的概念。這是為什麼Python如此優秀的原因之一——它是由一群希望看到一個更加優秀的Python的人創造並經常改進著的。

高層語言
當你用Python語言編寫程序的時候,你無需考慮諸如如何管理你的程序使用的內存一類的底層細節。

可移植性
由於它的開源本質,Python已經被移植在許多平台上(經過改動使它能夠工作在不同平台上)。如果你小心地避免使用依賴於系統的特性,那麼你的所有Python程序無需修改就可以在下述任何平台上面運行。

這些平台包括Linux、Windows、FreeBSD、Macintosh、Solaris、OS/2、Amiga、AROS、AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、VxWorks、PlayStation、Sharp Zaurus、Windows CE甚至還有PocketPC!

解釋性
這一點需要一些解釋。

一個用編譯性語言比如C或C++寫的程序可以從源文件(即C或C++語言)轉換到一個你的計算機使用的語言(二進制代碼,即0和1)。這個過程通過編譯器和不同的標記、選項完成。當你運行你的程序的時候,連接/轉載器軟體把你的程序從硬碟復制到內存中並且運行。

而Python語言寫的程序不需要編譯成二進制代碼。你可以直接從源代碼 運行 程序。在計算機內部,Python解釋器把源代碼轉換成稱為位元組碼的中間形式,然後再把它翻譯成計算機使用的機器語言並運行。事實上,由於你不再需要擔心如何編譯程序,如何確保連接轉載正確的庫等等,所有這一切使得使用Python更加簡單。由於你只需要把你的Python程序拷貝到另外一台計算機上,它就可以工作了,這也使得你的Python程序更加易於移植。

面向對象
Python即支持面向過程的編程也支持面向對象的編程。在 面向過程 的語言中,程序是由過程或僅僅是可重用代碼的函數構建起來的。在 面向對象 的語言中,程序是由數據和功能組合而成的對象構建起來的。與其他主要的語言如C++和Java相比,Python以一種非常強大又簡單的方式實現面向對象編程。

可擴展性
如果你需要你的一段關鍵代碼運行得更快或者希望某些演算法不公開,你可以把你的部分程序用C或C++編寫,然後在你的Python程序中使用它們。

可嵌入性
你可以把Python嵌入你的C/C++程序,從而向你的程序用戶提供腳本功能。

豐富的庫
Python標准庫確實很龐大。它可以幫助你處理各種工作,包括正則表達式、文檔生成、單元測試、線程、資料庫、網頁瀏覽器、CGI、FTP、電子郵件、XML、XML-RPC、HTML、WAV文件、密碼系統、GUI(圖形用戶界面)、Tk和其他與系統有關的操作。記住,只要安裝了Python,所有這些功能都是可用的。這被稱作Python的「功能齊全」理念。

除了標准庫以外,還有許多其他高質量的庫,如wxPython、Twisted和Python圖像庫等等。

⑺ 如何深入理解Python中的面向對象的思維

ython使用類(class)和對象(object),進行面向對象(object-oriented programming,簡稱OOP)的編程。
面向對象的最主要目的是提高程序的重復使用性。我們這么早切入面向對象編程的原因是,Python的整個概念是基於對象的。了解OOP是進一步學習Python的關鍵。
下面是對面向對象的一種理解,基於分類。
相近對象,歸為類
在人類認知中,會根據屬性相近把東西歸類,並且給類別命名。比如說,鳥類的共同屬性是有羽毛,通過產卵生育後代。任何一隻特別的鳥都在鳥類的原型基礎上的。

對這方面感興趣,想要學習python或者想要了解python可以加群:623715703
面向對象就是模擬了以上人類認知過程。在Python語言,為了聽起來酷,我們把上面說的「東西」稱為對象(object)。
面向對象的基本思想是封裝,繼承,多態。
首先是繼承:
定義一個類:
復制代碼 代碼如下:
class Bird(object):
have_feather = True
way_of_reproction = 'egg'
調用這個類:
summer = Bird()
print summer.way_of_reproction
與Java不同是,Python是不需要new來實例化類的。
同樣,Python的類下面是可以定方法的:
def say(self, word='hi hi'):
print 'i say :' + word
注意一點,所有類的函數,必須至少帶有一個參數,這個參數必須是self。
類以外的函數沒有這一個限制。
chk = Chicken()
print chk.have_feather
print chk.sat('hello')
__init__()方法
__init__()是一個特殊方法(special method)。Python里會有一些特殊方法,Python會以特別的方式處理它們。特殊方法的名字的特點是前後都有兩個下劃線。

__init__()方法的特殊在於,如果你在類中定義了這個方法,一旦你根據這個類建立對象,Python就會自動調用這個方法(這個過程也叫初始化)。
如:
class happyBird(Bird):
def __init__(self,more_words):
print 'We are happy birds.',more_words
hb = happyBird('Happy,Happy!')
父類方法的重載:
class Hello(object):
name = 'hello'
def __init__(self):
self.name='my name is hello'
#類中的參數必須帶有self參數
def sayhi(self):
print 'hi you'
class World(Hello):
#這里訪問的是父類初始化的變數名
print 'before:',Hello.name
super(World,self).__init__()
#由於調用了父類的初始化構造函數,繼承了父類的變數的改變
print 'after:',self.name
#近似於方法重載
def sayhi(self,word='baby'):
#調用父類sayhi方法
super(World,self).sayhi()
print 'hi '+word
def sayWorld(self):
print 'hi,hello world'
if __name__ == '__main__':
c = World()
c.sayhi()
c.sayWorld()

另外,python是允許多繼承的,但是這個是個非常危險的操作,建議不要隨便使用。
關於Python的多態,就像JavaScript一樣,直接訪問對象的屬性,不需要使用介面,沒有類型轉換。
對於類型的判斷,有抓們的type()函數,和isinstance()函數判斷是否某個函數的子類。
isinstance(object, classinfo)
判斷實例是否是這個類或者object是變數
classinfo 是類型(tuple,dict,int,float)
判斷變數是否是這個類型
class objA:
pass
A = objA()
B = 'a','v'
C = 'a string'
print isinstance(A, objA)
print isinstance(B, tuple)
print isinstance(C, basestring)
輸出結果:
True

將東西根據屬性歸類 ( 將object歸為class )
方法是一種屬性,表示動作
用繼承來說明父類-子類關系。子類自動具有父類的所有屬性。
self代表了根據類定義而創建的對象。
建立對一個對象: 對象名 = 類名()
引用對象的屬性: object.attribute
希望小夥伴們早日成為大牛!

⑻ C 語言和 Python,該從哪個入門編程

先說結論,建議C
首先你要看看自己是要干什麼,學習X語言只有兩個目的:
1,成為一名軟狗。
2,成為一名偽軟狗。
如果你要成為一名軟狗,請學習C。因為C是一貧如洗的語言,C能給你最好的邏輯鍛煉而不是給你個庫你看看有什麼功能。
如果你要成為一名偽軟狗,請學習C。
為啥呢,笑,因為你連C都不會怎麼裝x啊。當然這不是重點。(逃
由於C的先天的單純和面向過程的特性,以及略現死板的編碼要求,都讓人能夠快速掌握編程思想。但是C要學到什麼程度就見仁見智了。比如我要成為一個嵌入式程序員,我就必須對C的各種小庫了如指掌,各種函數什麼功能,指針怎麼指來指去。還需要明確內存操作等相關問題。最後類似於用C來實現某些位運算啊I/O調用啊小破標志位動來動去啊。
但是我要成為一個工業生產程序員我就了解C的基本思想就行了,無需了解C中相對不容易調用的庫,也不用太考慮指針和位運算。因為我的思路是要向面向對象甚至面向切面拓展的。
至於python,我也是很喜歡啊,最近剛剛入門。感覺好簡潔啊,好歡樂啊,很多C#搞半天的玩意一會兒就寫完了啊,站在了巨人肩膀上真是爽啊,前人栽樹好乘涼啊!!
不過這都是我使用C=》C++(也就大學學了點)=》C#後的感覺。
要是我上來學的是python,我的感覺估計就是哎我去怎麼怎麼坑爹這語法,哎我去這個實現怎麼這么費勁,哎我去縮進和邏輯怎麼沒關系。。。
先入為主的編程思想,很影響後續語言的學習的。
不過Python也很不錯,可以相當快速度入門,急速做出東西。學習曲線比較平緩而且最重要的是比較有成就感。
總結一下吧:
如果你想要作為一個程序員生活下去,請以C入門,沒錯的。
如果你想要在小白面前一展談資,請以C入門,妥妥的。
如果你想要迅速做出需要的東西,請怒學Python,學成了記得給我培訓下。
如果你想要後續撬開面向對象或面向切面大門,請學C。
對Java等面向對象語言沒興趣就是想寫代碼,Python。
以上。

⑼ 如何理解 Python

簡單例子:
def foo():
print('i am foo')

現在有一個新的需求,希望可以記錄下函數的執行日誌,於是在代碼中添加日誌代碼:
def foo():
print('i am foo')
logging.info("foo is running")

bar()、bar2()也有類似的需求,怎麼做?再寫一個logging在bar函數里?這樣就造成大量雷同的代碼,為了減少重復寫代碼,我們可以這樣做,重新定義一個函數:專門處理日誌 ,日誌處理完之後再執行真正的業務代碼
def use_logging(func):
logging.warn("%s is running" % func.__name__)
func()

def bar():
print('i am bar')

use_logging(bar)

邏輯上不難理解, 但是這樣的話,我們每次都要將一個函數作為參數傳遞給use_logging函數。而且這種方式已經破壞了原有的代碼邏輯結構,之前執行業務邏輯時,執行運行bar(),但是現在不得不改成use_logging(bar)。那麼有沒有更好的方式的呢?當然有,答案就是裝飾器。

簡單裝飾器

def use_logging(func):

def wrapper(*args, **kwargs):
logging.warn("%s is running" % func.__name__)
return func(*args, **kwargs)
return wrapper

def bar():
print('i am bar')

bar = use_logging(bar)
bar()

函數use_logging就是裝飾器,它把執行真正業務方法的func包裹在函數裡面,看起來像bar被use_logging裝飾了。在這個例子中,函數進入和退出時 ,被稱為一個橫切面(Aspect),這種編程方式被稱為面向切面的編程(Aspect-Oriented Programming)。
@符號是裝飾器的語法糖,在定義函數的時候使用,避免再一次賦值操作

def use_logging(func):

def wrapper(*args, **kwargs):
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper

@use_logging
def foo():
print("i am foo")

@use_logging
def bar():
print("i am bar")

bar()

如上所示,這樣我們就可以省去bar = use_logging(bar)這一句了,直接調用bar()即可得到想要的結果。如果我們有其他的類似函數,我們可以繼續調用裝飾器來修飾函數,而不用重復修改函數或者增加新的封裝。這樣,我們就提高了程序的可重復利用性,並增加了程序的可讀性。

裝飾器在Python使用如此方便都要歸因於Python的函數能像普通的對象一樣能作為參數傳遞給其他函數,可以被賦值給其他變數,可以作為返回值,可以被定義在另外一個函數內。

帶參數的裝飾器
裝飾器還有更大的靈活性,例如帶參數的裝飾器:在上面的裝飾器調用中,比如@use_logging,該裝飾器唯一的參數就是執行業務的函數。裝飾器的語法允許我們在調用時,提供其它參數,比如@decorator(a)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。
def use_logging(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "warn":
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper

return decorator

@use_logging(level="warn")
def foo(name='foo'):
print("i am %s" % name)

foo()

上面的use_logging是允許帶參數的裝飾器。它實際上是對原有裝飾器的一個函數封裝,並返回一個裝飾器。我們可以將它理解為一個含有參數的閉包。當我 們使用@use_logging(level="warn")調用的時候,Python能夠發現這一層的封裝,並把參數傳遞到裝飾器的環境中。

類裝飾器
再來看看類裝飾器,相比函數裝飾器,類裝飾器具有靈活度大、高內聚、封裝性等優點。使用類裝飾器還可以依靠類內部的\_\_call\_\_方法,當使用 @ 形式將裝飾器附加到函數上時,就會調用此方法。

class Foo(object):
def __init__(self, func):
self._func = func

def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')

@Foo
def bar():
print ('bar')

bar()

functools.wraps
使用裝飾器極大地復用了代碼,但是他有一個缺點就是原函數的元信息不見了,比如函數的docstring、__name__、參數列表,先看例子:
裝飾器
def logged(func):
def with_logging(*args, **kwargs):
print func.__name__ + " was called"
return func(*args, **kwargs)
return with_logging

函數
@logged
def f(x):
"""does some math"""
return x + x * x

該函數完成等價於:

def f(x):
"""does some math"""
return x + x * x
f = logged(f)

不難發現,函數f被with_logging取代了,當然它的docstring,__name__就是變成了with_logging函數的信息了。
print f.__name__ # prints 'with_logging'
print f.__doc__ # prints None

這個問題就比較嚴重的,好在我們有functools.wraps,wraps本身也是一個裝飾器,它能把原函數的元信息拷貝到裝飾器函數中,這使得裝飾器函數也有和原函數一樣的元信息了。
from functools import wraps
def logged(func):
@wraps(func)
def with_logging(*args, **kwargs):
print func.__name__ + " was called"
return func(*args, **kwargs)
return with_logging

@logged
def f(x):
"""does some math"""
return x + x * x

print f.__name__ # prints 'f'
print f.__doc__ # prints 'does some math'

內置裝飾器
@staticmathod、@classmethod、@property
裝飾器的順序

@a
@b
@c
def f ():

等效於

f = a(b(c(f)))

⑽ 如何理解Python裝飾器

理解Python中的裝飾器
@makebold
@makeitalic
def say():
return "Hello"

列印出如下的輸出:
<b><i>Hello<i></b>

你會怎麼做?最後給出的答案是:

def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped

def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped

@makebold
@makeitalic
def hello():
return "hello world"

print hello() ## 返回 <b><i>hello world</i></b>

現在我們來看看如何從一些最基礎的方式來理解Python的裝飾器。英文討論參考Here。
裝飾器是一個很著名的設計模式,經常被用於有切面需求的場景,較為經典的有插入日誌、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數中與函數功能本身無關的雷同代碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。
1.1. 需求是怎麼來的?
裝飾器的定義很是抽象,我們來看一個小例子。

def foo():
print 'in foo()'
foo()

這是一個很無聊的函數沒錯。但是突然有一個更無聊的人,我們稱呼他為B君,說我想看看執行這個函數用了多長時間,好吧,那麼我們可以這樣做:

import time
def foo():
start = time.clock()
print 'in foo()'
end = time.clock()
print 'used:', end - start

foo()

很好,功能看起來無懈可擊。可是蛋疼的B君此刻突然不想看這個函數了,他對另一個叫foo2的函數產生了更濃厚的興趣。
怎麼辦呢?如果把以上新增加的代碼復制到foo2里,這就犯了大忌了~復制什麼的難道不是最討厭了么!而且,如果B君繼續看了其他的函數呢?
1.2. 以不變應萬變,是變也
還記得嗎,函數在Python中是一等公民,那麼我們可以考慮重新定義一個函數timeit,將foo的引用傳遞給他,然後在timeit中調用foo並進行計時,這樣,我們就達到了不改動foo定義的目的,而且,不論B君看了多少個函數,我們都不用去修改函數定義了!

import time

def foo():
print 'in foo()'

def timeit(func):
start = time.clock()
func()
end =time.clock()
print 'used:', end - start

timeit(foo)

看起來邏輯上並沒有問題,一切都很美好並且運作正常!……等等,我們似乎修改了調用部分的代碼。原本我們是這樣調用的:foo(),修改以後變成了:timeit(foo)。這樣的話,如果foo在N處都被調用了,你就不得不去修改這N處的代碼。或者更極端的,考慮其中某處調用的代碼無法修改這個情況,比如:這個函數是你交給別人使用的。
1.3. 最大限度地少改動!
既然如此,我們就來想想辦法不修改調用的代碼;如果不修改調用代碼,也就意味著調用foo()需要產生調用timeit(foo)的效果。我們可以想到將timeit賦值給foo,但是timeit似乎帶有一個參數……想辦法把參數統一吧!如果timeit(foo)不是直接產生調用效果,而是返回一個與foo參數列表一致的函數的話……就很好辦了,將timeit(foo)的返回值賦值給foo,然後,調用foo()的代碼完全不用修改!

#-*- coding: UTF-8 -*-
import time

def foo():
print 'in foo()'

# 定義一個計時器,傳入一個,並返回另一個附加了計時功能的方法
def timeit(func):

# 定義一個內嵌的包裝函數,給傳入的函數加上計時功能的包裝
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start

# 將包裝後的函數返回
return wrapper

foo = timeit(foo)
foo()

這樣,一個簡易的計時器就做好了!我們只需要在定義foo以後調用foo之前,加上foo = timeit(foo),就可以達到計時的目的,這也就是裝飾器的概念,看起來像是foo被timeit裝飾了。在在這個例子中,函數進入和退出時需要計時,這被稱為一個橫切面(Aspect),這種編程方式被稱為面向切面的編程(Aspect-Oriented Programming)。與傳統編程習慣的從上往下執行方式相比較而言,像是在函數執行的流程中橫向地插入了一段邏輯。在特定的業務領域里,能減少大量重復代碼。面向切面編程還有相當多的術語,這里就不多做介紹,感興趣的話可以去找找相關的資料。
這個例子僅用於演示,並沒有考慮foo帶有參數和有返回值的情況,完善它的重任就交給你了 :)
上面這段代碼看起來似乎已經不能再精簡了,Python於是提供了一個語法糖來降低字元輸入量。

import time

def timeit(func):
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper

@timeit
def foo():
print 'in foo()'

foo()

重點關注第11行的@timeit,在定義上加上這一行與另外寫foo = timeit(foo)完全等價,千萬不要以為@有另外的魔力。除了字元輸入少了一些,還有一個額外的好處:這樣看上去更有裝飾器的感覺。
-------------------
要理解python的裝飾器,我們首先必須明白在Python中函數也是被視為對象。這一點很重要。先看一個例子:

def shout(word="yes") :
return word.capitalize()+" !"

print shout()
# 輸出 : 'Yes !'

# 作為一個對象,你可以把函數賦給任何其他對象變數

scream = shout

# 注意我們沒有使用圓括弧,因為我們不是在調用函數
# 我們把函數shout賦給scream,也就是說你可以通過scream調用shout

print scream()
# 輸出 : 'Yes !'

# 還有,你可以刪除舊的名字shout,但是你仍然可以通過scream來訪問該函數

del shout
try :
print shout()
except NameError, e :
print e
#輸出 : "name 'shout' is not defined"

print scream()
# 輸出 : 'Yes !'

我們暫且把這個話題放旁邊,我們先看看python另外一個很有意思的屬性:可以在函數中定義函數:

def talk() :

# 你可以在talk中定義另外一個函數
def whisper(word="yes") :
return word.lower()+"...";

# ... 並且立馬使用它

print whisper()

# 你每次調用'talk',定義在talk裡面的whisper同樣也會被調用
talk()
# 輸出 :
# yes...

# 但是"whisper" 不會單獨存在:

try :
print whisper()
except NameError, e :
print e
#輸出 : "name 'whisper' is not defined"*

函數引用
從以上兩個例子我們可以得出,函數既然作為一個對象,因此:
1. 其可以被賦給其他變數
2. 其可以被定義在另外一個函數內
這也就是說,函數可以返回一個函數,看下面的例子:

def getTalk(type="shout") :

# 我們定義另外一個函數
def shout(word="yes") :
return word.capitalize()+" !"

def whisper(word="yes") :
return word.lower()+"...";

# 然後我們返回其中一個
if type == "shout" :
# 我們沒有使用(),因為我們不是在調用該函數
# 我們是在返回該函數
return shout
else :
return whisper

# 然後怎麼使用呢 ?

# 把該函數賦予某個變數
talk = getTalk()

# 這里你可以看到talk其實是一個函數對象:
print talk
#輸出 : <function shout at 0xb7ea817c>

# 該對象由函數返回的其中一個對象:
print talk()

# 或者你可以直接如下調用 :
print getTalk("whisper")()
#輸出 : yes...

還有,既然可以返回一個函數,我們可以把它作為參數傳遞給函數:

def doSomethingBefore(func) :
print "I do something before then I call the function you gave me"
print func()

doSomethingBefore(scream)
#輸出 :
#I do something before then I call the function you gave me
#Yes !

這里你已經足夠能理解裝飾器了,其他它可被視為封裝器。也就是說,它能夠讓你在裝飾前後執行代碼而無須改變函數本身內容。
手工裝飾
那麼如何進行手動裝飾呢?

# 裝飾器是一個函數,而其參數為另外一個函數
def my_shiny_new_decorator(a_function_to_decorate) :

# 在內部定義了另外一個函數:一個封裝器。
# 這個函數將原始函數進行封裝,所以你可以在它之前或者之後執行一些代碼
def the_wrapper_around_the_original_function() :

# 放一些你希望在真正函數執行前的一些代碼
print "Before the function runs"

# 執行原始函數
a_function_to_decorate()

# 放一些你希望在原始函數執行後的一些代碼
print "After the function runs"

#在此刻,"a_function_to_decrorate"還沒有被執行,我們返回了創建的封裝函數
#封裝器包含了函數以及其前後執行的代碼,其已經准備完畢
return the_wrapper_around_the_original_function

# 現在想像下,你創建了一個你永遠也不遠再次接觸的函數
def a_stand_alone_function() :
print "I am a stand alone function, don't you dare modify me"

a_stand_alone_function()
#輸出: I am a stand alone function, don't you dare modify me

# 好了,你可以封裝它實現行為的擴展。可以簡單的把它丟給裝飾器
# 裝飾器將動態地把它和你要的代碼封裝起來,並且返回一個新的可用的函數。
a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function_decorated()
#輸出 :
#Before the function runs
#I am a stand alone function, don't you dare modify me
#After the function runs

現在你也許要求當每次調用a_stand_alone_function時,實際調用卻是a_stand_alone_function_decorated。實現也很簡單,可以用my_shiny_new_decorator來給a_stand_alone_function重新賦值。

a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function()
#輸出 :
#Before the function runs
#I am a stand alone function, don't you dare modify me
#After the function runs

# And guess what, that's EXACTLY what decorators do !

裝飾器揭秘
前面的例子,我們可以使用裝飾器的語法:

@my_shiny_new_decorator
def another_stand_alone_function() :
print "Leave me alone"

another_stand_alone_function()
#輸出 :
#Before the function runs
#Leave me alone
#After the function runs

當然你也可以累積裝飾:

def bread(func) :
def wrapper() :
print "</''''''\>"
func()
print "<\______/>"
return wrapper

def ingredients(func) :
def wrapper() :
print "#tomatoes#"
func()
print "~salad~"
return wrapper

def sandwich(food="--ham--") :
print food

sandwich()
#輸出 : --ham--
sandwich = bread(ingredients(sandwich))
sandwich()
#outputs :
#</''''''\>
# #tomatoes#
# --ham--
# ~salad~
#<\______/>

使用python裝飾器語法:

@bread
@ingredients
def sandwich(food="--ham--") :
print food

sandwich()
#輸出 :
#</''''''\>
# #tomatoes#
# --ham--
# ~salad~
#<\______/>

閱讀全文

與Python如何實現面相切面相關的資料

熱點內容
數學奇跡神奇運演算法 瀏覽:359
大廠的程序員的水平如何 瀏覽:700
遺傳演算法入門經典書籍 瀏覽:878
源碼炮台腳本 瀏覽:620
在位編輯命令 瀏覽:347
曲式分析基礎教程pdf 瀏覽:14
php生成靜態html頁面 瀏覽:964
怎麼分割pdf 瀏覽:812
壓縮垃圾報警器 瀏覽:628
小公司一般都用什麼伺服器 瀏覽:967
java獲取時間gmt時間 瀏覽:820
為什麼csgo一直連接不到伺服器 瀏覽:504
安卓登ins需要什麼 瀏覽:836
機器人演算法的難點 瀏覽:226
全自動化編程 瀏覽:726
程序員高薪限制 瀏覽:693
壓縮圖片壓縮 瀏覽:75
美國發明解壓魔方 瀏覽:302
電腦怎麼備案網上伺服器 瀏覽:515
旅行商問題Python寫法 瀏覽:952