Python第九周 學習筆記(1)
阿新 • • 發佈:2018-05-20
學習筆記描述器
get(self, instance, owner)
- 訪問屬性時調用
set(self, instance, value)
- 當對屬性賦值時調用
delete(self, instance)
-
刪除屬性時調用
- self指代當前實例
- instance是owner的實例
- owner是屬性的所屬的類
-
描述器實現前提是描述器類實例作為類屬性
- 當只實現get時 (非數據描述符),屬性查找順序是本實例優先,get方法次之
- 當實現get和set時(數據描述符) ,屬性查找順序是get方法優先
本質
- 給類添加描述器時可以顯示添加類屬性,或者用setattr註入
註意所謂的類屬性不僅僅類似與x=A()的屬性,類中定義的函數也是類屬性
模擬staticmethod與classmethod
from functools import partial class StaticMethod: def __init__(self, fn): self.fn = fn def __get__(self, instance, owner): return self.fn class ClassMethod: def __init__(self, fn): self.fn = fn def __get__(self, instance, owner): return partial(self.fn, owner) class Test: @StaticMethod def s_mtd(): # s_mtd = StaticMethod(s_mtd) print(‘s_mtd‘) @ClassMethod def c_mtd(cls): # c_mtd = ClassMethod(c_mtd) print(‘c_mtd‘, cls) if __name__ == ‘__main__‘: Test.s_mtd() Test.c_mtd()
模擬property
class Property: def __init__(self, fget=None, fset=None): self.fget = fget self.fset = fset def __get__(self, instance, owner): return self.fget(instance) def __set__(self, instance, value): self.fset(instance, value) def getter(self): pass def setter(self, fset): self.fset = fset return self class Person: def __init__(self, name, age): self._name = name self._age = age @Property def name(self): # name=Property(name) return self._name @name.setter def name(self, value): # name=Property(name).setter(name) (value) self._name = value @Property def age(self): # name=Property(name) return self._age @age.setter def age(self, value): # name=Property(name).setter(name) (value) self._age = value
校驗參數類型
普通裝飾器
import inspect
class TypeCheck:
def __init__(self, key, type):
print(‘TC init‘)
self.key = key
self.type = type
def __get__(self, instance, owner):
print(‘TC get‘)
if instance is not None:
return instance.__dict__[self.key]
return self
def __set__(self, instance, value):
print(‘TC set‘)
if not isinstance(value, self.type):
raise TypeError
instance.__dict__[self.key] = value
def typeassert(cls):
params = inspect.signature(cls).parameters
for name, type in params.items():
if type != type.empty:
setattr(cls, name, type.annotation)
return cls
@typeassert
class Person:
name = TypeCheck(‘name‘, str)
age = TypeCheck(‘age‘, int)
def __init__(self, name: str, age: int):
self.name = name
self.age = age
tom = Person(‘tom‘, 12)
print(tom.name)
類裝飾器
import inspect
class TypeCheck:
def __init__(self, key, type):
print(‘TC init‘)
self.key = key
self.type = type
def __get__(self, instance, owner):
print(‘TC get‘)
if instance is not None:
return instance.__dict__[self.key]
return self
def __set__(self, instance, value):
print(‘TC set‘)
if not isinstance(value, self.type):
raise TypeError
instance.__dict__[self.key] = value
class TypeAssert:
def __init__(self, cls):
self.cls = cls
def __call__(self, name, age):
params = inspect.signature(self.cls).parameters
for key, type in params.items():
if type != type.empty:
setattr(self.cls, key, TypeCheck(key, type.annotation))
return self.cls(name, age)
@TypeAssert
class Person: # Person = TypeAssert(Person)
name = TypeCheck(‘name‘, str)
age = TypeCheck(‘age‘, int)
def __init__(self, name: str, age: int):
self.name = name
self.age = age
tom = Person(‘tom‘, ‘12‘)
print(tom.name)
鏈表
class Node:
"""
Description: Node Class
attr item: current Node`s data
attr next: points to the next Node
attr past: points to the last Node
"""
def __init__(self, item: object):
self.__item = item
self.__next = None
self.__past = None
@property
def item(self):
return self.__item
@item.setter
def item(self, value):
self.__item = value
@property
def next(self):
return self.__next
@next.setter
def next(self, value: object):
self.__next = value
@property
def past(self):
return self.__past
@past.setter
def past(self, value: object):
self.__past = value
class LinkedList:
"""
Description: Base class LinkedList
"""
def __init__(self):
self.cur = None
self.head = None
self.length = 0
def append(self, no: object):
raise Exception(‘Base Method‘)
def iternodes(self):
raise Exception(‘Base Method‘)
def pop(self):
raise Exception(‘Base Method‘)
def insert(self, position: int, value: object):
raise Exception(‘Base Method‘)
def remove(self, value: object):
raise Exception(‘Base Method‘)
class SingleLinkedList(LinkedList):
"""
Description:
attr head: head Node
attr cur: current Node
method append(): append Node
"""
def __init__(self):
super().__init__()
def __iter__(self):
cur_node = self.head
while True:
yield cur_node.item
if not cur_node.next:
break
cur_node = cur_node.next
def __getitem__(self, item):
cur_node = self.head
if isinstance(item, slice):
pass
else:
for _ in range(item):
cur_node = cur_node.next
return cur_node.item
def __setitem__(self, key, value):
cur_node = self.head
for _ in range(key):
cur_node = cur_node.next
cur_node.item = value
def append(self, no: object):
if self.length == 0:
self.cur = Node(no)
self.head = self.cur
else:
self.cur.next = Node(no)
self.cur = self.cur.next
self.length += 1
sl = SingleLinkedList()
sl.append(1)
sl.append(2)
for i in sl:
print(i)
sl[1] = 999
sl[0] = 234
for i in sl:
print(i)
class DoubleLinkedList(LinkedList):
"""
Description:
attr head:
attr cur:
method append:
method pop:
method insert:
method remove:
method iternodes:
"""
def __init__(self):
super().__init__()
def __iter__(self):
cur_node = self.head
while True:
yield cur_node.item
if not cur_node.next:
break
cur_node = cur_node.next
def __reversed__(self):
cur_node = self.cur
while True:
yield cur_node.item
if not cur_node.past:
break
cur_node = cur_node.past
def __getitem__(self, item):
cur_node = self.head
if isinstance(item, slice):
pass
else:
for _ in range(item):
cur_node = cur_node.next
return cur_node.item
def __setitem__(self, key, value):
cur_node = self.head
for _ in range(key):
cur_node = cur_node.next
cur_node.item = value
def append(self, no: object):
if self.length == 0:
self.cur = Node(no)
self.head = self.cur
else:
temp = self.cur
self.cur.next = Node(no)
self.cur = self.cur.next
self.cur.past = temp
self.length += 1
def pop(self):
pop_node = self.cur
pop_node.past.next = None
self.cur = self.cur.past
self.length -= 1
return pop_node
def insert(self, position: int, value: object):
cur_node = self.head
new_node = Node(value)
for _ in range(position - 1):
cur_node = cur_node.next
next_node = cur_node.next
cur_node.next = new_node
new_node.past = cur_node
new_node.next = next_node
next_node.past = new_node
def remove(self, value: object):
cur_node = self.head
while True:
if cur_node.item == value:
cur_node.past.next = cur_node.next
cur_node.next.past = cur_node.past
break
elif not cur_node.next:
raise Exception(‘NodeNotFound‘)
cur_node = cur_node.next
def iternodes(self, *, reverse=False):
if not reverse:
cur_node = self.head
while True:
yield cur_node.item
if not cur_node.next:
break
cur_node = cur_node.next
else:
cur_node = self.cur
while True:
yield cur_node.item
if not cur_node.past:
break
cur_node = cur_node.past
異常處理
產生異常
raise 異常實例
- Python解釋器自己檢測到異常並引發它
異常捕獲
try:
待捕獲異常的代碼塊
except [異常類型] as e:
異常的處理代碼塊
else:
...
finally:
...
- e為異常的實例
- 可寫多個except
- else 沒有任何異常發生則執行
- finally語句塊無論如何都會執行
BaseException
- 所有內建異常類的基類
SystemExit
- sys.exit()引發的異常,異常不捕獲處理,直接交給Python解釋器,解釋器退出
KeyboardInterrupt
- 命令行使用Ctrl+C終端操作
Exception
- 所有內建、非系統退出的異常的基類,自定義異常需要繼承它
SyntaxError語法錯誤
- 此錯誤不可捕獲
ArithmeticError
- 算術計算錯誤,子類有除零異常等
LookupError
- 使用映射的鍵或序列的索引無效時引發的異常的基類:IndexError,KeyError
模塊化
import ... 與import ... as ...
- 找到制定的模塊,加載和初始化它,生成模塊對象
-
在import所在的作用域的局部命名空間中,增加名稱和上一步創建的對象關聯
- 導入頂級模塊,其名稱會加入到本地名詞空間中(dir()),並綁定到其模塊對象
- 導入非頂級模塊,至將其頂級模塊名稱加入到本地名詞空間中,導入的模塊必須用完全限定名訪問
- 如果使用as,as後的名稱直接綁定到導入的模塊對象中,並將該名稱加入到本地名詞空間中
from ... import ...與from ... import ... as ...
- from後指定的模塊名只加載並初始化,不導入
- 對於import子句後的名稱
- 先查from導入的模塊是否具有該名稱屬性,如果不是,則嘗試導入該名稱的子模塊
自定義模塊
- 命名規範
- 全小寫,下劃線來分割
模塊搜索順序
sys.path
- 返回列表
- 可被修改,追加新路徑
路徑查找順序
- 程序主目錄
- PYTHONPATH目錄
- 標準庫目錄
sys.modules
- 返回字典
- 記錄所有加載的模塊
模塊運行
name
- 模塊名,如不指定就是文件名
- 解釋器初始化時會初始化sys.module字典,創建builtins模塊、main模塊、sys模塊,sys.path
if name == ‘main‘
- 用於模塊功能測試
- 避免主模塊變更的副作用
模塊的屬性
- file 源文件路徑
- cached 編譯後的字節碼文件路徑
- spec 顯示模塊規範
- name 模塊名
- package 當模塊是包,同name,否則可以設置為頂級模塊的空字符串
包 Package
- 目錄下有一個init.py文件,導入包時,此文件內容代表此包
子模塊
- 包目錄下的py文件、子目錄都是其子模塊
模塊和包總結
- 導入子模塊一定會加載父模塊,導入父模塊一定不會導入子模塊
包是特殊的模塊,包含path屬性
絕對導入,相對導入
絕對導入
- 總是去搜索模塊搜索路徑中找
相對導入
- 只能在包內使用,且只能用在from中
- . 表示當前目錄
- .. 表示上一級目錄
- ... 表示上上級目錄
訪問控制
-
from ... import *
- 使用此方法導入模塊時,以_和__開頭的屬性不會導入
- 使用all
- 一個列表,每個元素都是模塊內的變量名
- 定義all後,from ... import * 只導入all內的屬性
包管理
-
setuptools
- 包管理的核心模塊
-
pip
- 目前包管理的事實標準
- wheel
- 以二進制安裝,不需要本地編譯
pip install wheel
創建setup.py文件
# from distutils.core import setup # 可能失敗
from setuptools import setup
setup(name=‘Distutils‘,
version=‘1.0‘,
description=‘Python Distribution Utilities‘,
author=‘Greg Ward‘,
author_email=‘[email protected]‘,
url=‘https://www.python.org/sigs/distutils-sig/‘,
packages=[‘distutils‘, ‘distutils.command‘],
)
- package內容是要管理的包
查詢命令幫助
python setup.py cmd -help
build
- 創建一個build目錄
python setup.py build
- build得到的文件,直接拷貝到其他項目就可以用
install
python setup.py install
- 如果沒有build,會先build編譯,然後安裝
sdist
python setup.py sdist
- 創建源代碼的分發包
- 在其他地方解壓縮這個文件,裏面有setup.py,就可以使用python setup.py install安裝,也可以
- pip install XXX.zip直接使用pip安裝這個壓縮包
插件化開發
動態導入
- 運行時,根據用戶需求,找到模塊的資源動態加載起來
- import(name, globals=None, locals=None, fromlist=(), level=0)
- name 模塊名
- import 本質上就是調用此函數(sys = impot(‘sys‘) 等價於import sys),但建議不直接使用,建議使用
- importlib.import_module(name, package=None)
- 支持絕對導入和相對導入,如果是相對導入,package必須設置
插件化編程技術
依賴的技術
- 反射:運行時獲取類型的信息,可以動態維護類型數據
- 動態import:使用importlib
- 多線程:可以開啟一個線程,等待用戶輸入,從而加載指定名稱的模塊
加載時機
- 程序啟動時
- 程序運行中
- 如插件過多,會導致程序啟動很慢,如果用戶需要時再加載,如果插件太大或依賴多,插件也會啟動慢。
- 因此先加載必須、常用插件,其他插件使用時,發現需要,動態載入
基礎知識補充
slot
- 字典為了查詢效率,必須用空間換時間
- 如果實例對象數量過大,那字典占用空間過大
- 如果類定義了slot,實例會省略建立dict
- 如果給實例增加不在slot的屬性會拋出Attribute異常
- slot可以定義為元組或列表,通常用元組,省空間
- slot不會繼承給子類
未實現和未實現異常
- NotImplemented是個值,單值,是NotImplementedType類的實例
- NotImplementedError是類型,是異常,返回type
運算符重載中的反向方法
- 當正向方法返回NotImplemented時調用反向方法
git服務器搭建
gogs
軟件依賴
Mysql
安裝
useradd git
su - git
tar xf gogs*
cd gogs
mysql -uroot -p < scripts/mysql.sql
grant all on gogs.* to ‘gogs‘@‘%‘ identified by ‘gogs‘;
flush privileges;
配置文件
mkdir -p custom/conf
cd custom/conf
touch app.ini
啟動gogs
-
./gogs web
- 服務啟動
gogs下需要建立log目錄
root用戶操作
cp /home/git/gogs/scripts/init/centos/gogs /etc/init.d/
chmod +x /etc/init.d/gogs
chkconfig gogs on
service gogs start
首次登陸
http://IP:Port/install
Python第九周 學習筆記(1)