-
class
class后面緊接著是類名,類名命名規(guī)則大駝峰,緊接著是(object)滋捶,表示該類是從哪個(gè)類繼承下來的
定義類格式:
class 類名:
def 方法名(self, 參數(shù)):
pass
創(chuàng)建對(duì)象格式:
對(duì)象變量 = 類名()
- 初始化方法
使用類名()創(chuàng)建對(duì)象時(shí)盒粮,會(huì)自動(dòng)調(diào)用init方法
init方法用來定義一個(gè)類具有哪些屬性
class Person(object):
def __init__(self):
print("初始化方法")
self.name = "Naruto"
person = Person()
print(person.name)
class Cat(object):
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s愛吃魚' % self.name)
cat = Cat('Tom', 2)
print(cat.name)
cat.eat()
# 在類的外部給對(duì)象增加屬性(不推薦)
cat.gender = "公"
- 內(nèi)置方法del
對(duì)象從內(nèi)存中被銷毀前,會(huì)自動(dòng)調(diào)用del - 內(nèi)置方法str
必須返回一個(gè)字符串
如果在開發(fā)中嵌巷,使用print輸出一個(gè)對(duì)象時(shí)萄凤,希望打印自定義內(nèi)容,可以使用str方法搪哪。
class Dog(object):
def __init__(self, name):
self.name = name
print('%s 來嘍' % self.name)
def __del__(self):
print("%s 走了" % self.name)
def __str__(self):
return '我是小狗%s' % self.name
dog = Dog('xiaohei')
- 訪問限制
在Python中靡努,實(shí)例的變量名如果以__開頭,就變成了一個(gè)私有變量(private)晓折,只有內(nèi)部可以訪問惑朦,外部不能訪問。
class Students(object):
def __init__(self, name, score):
# 無法從外部訪問實(shí)例變量.__name和實(shí)例變量.__score
self.__name = name
self.__score = score
def get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_score(self, score):
if 0 <= score <= 100:
self.__score = score
else:
# raise ValueError('bad score')
self.__score = 0
student = Students('Naruto', 60)
print('%s: %s' % (student.get_name(), student.get_score()))
面向?qū)ο笕筇匦?/h5>
封裝: 根據(jù) 職責(zé) 將 屬性 和 方法 封裝 到一個(gè)抽象的 類 中;
繼承: 實(shí)現(xiàn)代碼的重用漓概,相同的代碼不需要重復(fù)的編寫;
多態(tài): 不同的對(duì)象調(diào)用相同的方法漾月,產(chǎn)生不同的執(zhí)行結(jié)果,增加代碼的靈活度;
-
封裝
封裝 是面向?qū)ο缶幊痰囊淮筇攸c(diǎn);
面向?qū)ο缶幊痰?第一步 —— 將 屬性 和 方法 封裝 到一個(gè)抽象的 類 中;
外界 使用 類 創(chuàng)建 對(duì)象胃珍,然后 讓對(duì)象調(diào)用方法;
對(duì)象方法的細(xì)節(jié) 都被 封裝 在 類的內(nèi)部梁肿。
"""
需求:
1.士兵許三多有一把AK47
2.士兵可以開火
3.槍能夠發(fā)射子彈
4.槍裝填子彈 可增加子彈數(shù)量
"""
class Gun(object):
def __init__(self, model):
self.model = model
self.buttet_count = 0
def shoot(self):
if self.buttet_count > 0:
self.buttet_count -= 1
print("射擊")
else:
print("%s沒子彈" % self.model)
def add_bullet(self, count):
print("裝子彈")
self.buttet_count += count
class Soldier(object):
def __init__(self, name):
self.name = name
self.gun = None
def add_gun(self, gun):
self.gun = gun
def add_bullet(self, count):
if self.gun is None:
print("沒有槍")
else:
self.gun.add_bullet(count)
def fire(self):
if self.gun is None:
print("士兵沒有槍")
else:
print("開火")
self.gun.shoot()
gun = Gun("AK47")
soldier = Soldier("許三多")
soldier.add_gun(gun)
soldier.add_bullet(20)
soldier.fire()
-
繼承
1.子類對(duì)象不能在自己的方法內(nèi)部蜓陌,直接訪問父類的 私有方法 或 私有屬性;
2.子類對(duì)象可以通過父類的公有方法 間接 訪問到 私有方法 和 私有屬性。
- 單繼承
class Animal(object):
def __init__(self, name):
self.name = name
def eat(self):
print("%s 吃" % self.name)
def drink(self):
print("%s 喝" % self.name)
def run(self):
print("%s 跑" % self.name)
def sleep(self):
print("%s 睡" % self.name)
class Dog(Animal):
def bark(self):
print("%s 叫" % self.name)
# 子類對(duì)象不能調(diào)用父類的私有方法
def __test(self):
print("Dog的私有方法")
# 子類對(duì)象可以通過調(diào)用父類的公有方法,間接調(diào)用父類的私有方法
def ttt(self):
print("Dog的公有方法")
self.__test()
class Cat(Animal):
def catch(self):
print("%s 抓老鼠" % self.name)
class RoaringDog(Dog):
def fly(self):
print("%s 會(huì)飛" % self.name)
# 重寫(override)父類方法
def bark(self):
# super().bark() # 同時(shí)執(zhí)行父類中的方法
print("%s叫的和神一樣" % self.name)
dog = Dog("旺財(cái)")
dog.eat()
dog.bark()
dog.ttt()
cat = Cat("湯姆")
cat.drink()
cat.catch()
xtq = RoaringDog('哮天犬')
xtq.run()
xtq.fly()
xtq.bark()
- 多繼承
子類可以擁有多個(gè)父類栈雳,并且具有所有父類的屬性和方法
注意:如果父類之間存在同名的屬性或方法护奈,應(yīng)該避免使用多繼承
class A(object):
def test(self):
print("A的test()方法")
class B(object):
def demo(self):
print("B的demo()方法")
class C(A, B):
pass
c = C()
c.test()
c.demo()
-
多態(tài)
不同的子類對(duì)象調(diào)用相同的父類方法,產(chǎn)生不同的執(zhí)行結(jié)果哥纫。
1.多態(tài)可以增加代碼的靈活度
2.以繼承 和 重寫父類方法 為前提
3.是調(diào)用方法的技巧峰伙,不會(huì)影響到類內(nèi)部設(shè)計(jì)
class Dog(object):
def __init__(self, name):
self.name = name
def game(self):
print("%s蹦蹦跳跳的玩耍~" % self.name)
class XiaoTianQuan(Dog):
def game(self):
print("%s飛到天上去玩耍" % self.name)
class Person(object):
def __init__(self, name):
self.name = name
def game_with_dog(self, dog):
print("%s 和 %s 快樂的玩耍" % (self.name, dog.name))
dog.game()
wangcai = Dog('旺財(cái)')
xiaolan = Person('小蘭')
xiaolan.game_with_dog(wangcai)
xiaotianquan = XiaoTianQuan('哮天犬')
xiaohong = Person('小紅')
xiaolan.game_with_dog(xiaotianquan)
- 類屬性 類方法 靜態(tài)方法
- 類屬性
實(shí)例屬性屬于各個(gè)實(shí)例所有,互不干擾;
類屬性屬于類所有,所有實(shí)例共享一個(gè)屬性;
不要對(duì)實(shí)例屬性和類屬性使用相同的名字,否則將產(chǎn)生難以發(fā)現(xiàn)的錯(cuò)誤.
訪問類屬性方法:
1.類名.類屬性
2.對(duì)象.類屬性(不推薦)
注意:如果使用 對(duì)象.類屬性 = 值 賦值語句划址,只會(huì)給對(duì)象添加一個(gè)屬性目锭,而不會(huì)影響到類屬性的值
- 類方法
類方法就是針對(duì)類對(duì)象定義的方法荧呐;
在類方法內(nèi)部可以直接訪問類對(duì)象或其它類方法;
類方法需要用@classmethod修飾器來標(biāo)識(shí)擅憔,告訴解釋器 這是一個(gè)類方法鸵闪;
語法:
@classmethod
def 類方法名(cls)
pass
注:類方法的第一個(gè)參數(shù)是cls,類似實(shí)例方法的self,在方法內(nèi)部可以通過cls訪問類屬性暑诸,也可以通過cls調(diào)用其它類方法.
class Tool(object):
count = 0
@classmethod
def show_tool_count(cls):
print('有%d個(gè)工具' % cls.count)
def __init__(self, name):
self.name = name
Tool.count += 1
tool1 = Tool('斧頭')
print('有%d個(gè)工具' % Tool.count)
tool2 = Tool('錘子')
print('有%d個(gè)工具' % Tool.count)
Tool.show_tool_count()
- 靜態(tài)方法
使用場(chǎng)景:在開發(fā)時(shí)蚌讼,如果需要在類中封裝一個(gè)方法,這個(gè)方法:
不需要 訪問實(shí)例屬性 或 調(diào)用實(shí)例方法个榕,也不需要 訪問類屬性 或 調(diào)用類方法篡石,
可以將這個(gè)方法封裝為靜態(tài)方法
語法:
@staticmethod
def 靜態(tài)方法名():
pass
調(diào)用方法: 類名.靜態(tài)方法()
class Dog(object):
dog_count = 0
@staticmethod
def run():
print("??")
Dog.run()
實(shí)例方法:方法內(nèi)部需要訪問實(shí)例屬性,實(shí)例方法內(nèi)部可以使用 類名. 訪問類屬性
類方法:方法內(nèi)部只需要訪問類屬性
靜態(tài)方法:方法內(nèi)部不需要訪問 實(shí)例屬性 和 類屬性
-
單例Singleton
目的 —— 讓 類 創(chuàng)建的對(duì)象西采,在系統(tǒng)中 只有 唯一的一個(gè)實(shí)例
每一次執(zhí)行 類名() 返回的對(duì)象凰萨,內(nèi)存地址是相同的
使用類名創(chuàng)建對(duì)象時(shí),會(huì)先調(diào)用new 方法為對(duì)象分配內(nèi)存空間
new是一個(gè)由object基類提供的內(nèi)置的靜態(tài)方法械馆,主要作用有兩個(gè):
1.在內(nèi)存中為對(duì)象分配內(nèi)存空間
2.返回對(duì)象的引用
python解釋器獲得對(duì)象的引用后胖眷,將引用作為第一個(gè)參數(shù)傳遞給init方法
注:new 是靜態(tài)方法,需主動(dòng)傳遞cls參數(shù)
class MusicPlayer(object):
instance = None
init_flag = False
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super().__new__(cls)
print("創(chuàng)建對(duì)象霹崎,分配內(nèi)存空間")
return cls.instance
def __init__(self):
# 初始化只執(zhí)行一次
if MusicPlayer.init_flag:
return
MusicPlayer.init_flag = True
print("播放器初始化")
player = MusicPlayer()
print(player)
player2 = MusicPlayer()
print(player2)
-
異常Exception
在程序開發(fā)中珊搀,如果 對(duì)某些代碼的執(zhí)行不能確定是否正確,可以增加 try(嘗試) 來 捕獲異常
捕獲異常最簡(jiǎn)單的語法格式:
try:
嘗試執(zhí)行的代碼
except:
出現(xiàn)錯(cuò)誤的處理
- 根據(jù)錯(cuò)誤類型捕獲異常
try:
num = int(input("請(qǐng)輸入一個(gè)整數(shù):"))
result = 8 / num
except ValueError as e:
print('except:', e)
except ZeroDivisionError as e:
print('except:', e)
except Exception as e:
print("未知錯(cuò)誤 %s" % e)
else:
# 沒有異常才會(huì)執(zhí)行的代碼
print(result)
finally:
# 無論是否有異常 都會(huì)執(zhí)行的代碼
print("-" * 50)
- 異常的傳遞
當(dāng)方法的執(zhí)行出現(xiàn)異常尾菇,會(huì)將異常傳遞給調(diào)用方法的一方;
如果傳遞到主程序食棕,仍然沒有異常處理,程序才會(huì)被終止;
提示:
在開發(fā)中错沽,可以在主函數(shù)中增加異常捕獲,在主函數(shù)中調(diào)用的其它函數(shù)眶拉,只要出現(xiàn)異常千埃,就會(huì)傳遞到主函數(shù)的異常捕獲中;
這樣就不需要在代碼中增加大量的異常捕獲,能夠保證代碼的整潔;
def demo1():
return int(input("請(qǐng)輸入一個(gè)整數(shù):"))
def demo2():
return demo1()
try:
demo2()
except ValueError:
print("請(qǐng)輸入正確整數(shù)")
except Exception as e:
print('未知錯(cuò)誤 %s' % e)
- 拋出raise異常
在開發(fā)中忆植,除了代碼執(zhí)行出錯(cuò)會(huì)拋出異常之外放可,還可以根據(jù)應(yīng)用程序特有的業(yè)務(wù)需求主動(dòng)拋出異常
步驟:
1.創(chuàng)建一個(gè)Exception 異常類
2.使用raise關(guān)鍵字拋出異常對(duì)象
def input_password():
password = input("請(qǐng)輸入密碼:")
if len(password) >= 8:
return password
raise Exception("密碼長(zhǎng)度不夠")
try:
print(input_password())
except Exception as e:
print(e)
- 模塊和包
- 模塊
每一個(gè)以擴(kuò)展名 py 結(jié)尾的 Python 源代碼文件都是一個(gè) 模塊谒臼;
模塊名 同樣也是一個(gè) 標(biāo)識(shí)符,需要符合標(biāo)識(shí)符的命名規(guī)則耀里;
在模塊中定義的 全局變量 蜈缤、函數(shù)、類 都是提供給外界直接使用的 工具冯挎;
模塊 就好比是 工具包底哥,要想使用這個(gè)工具包中的工具,就需要先 導(dǎo)入 這個(gè)模塊房官;
模塊的導(dǎo)入:
import 模塊1
import 模塊2
通過 模塊名. 使用模塊提供的全局變量趾徽、方法、類
模塊導(dǎo)入時(shí)指定別名: import 模塊1 as 模塊別名
局部導(dǎo)入from...import:
如果希望從一個(gè)模塊中導(dǎo)入部分工具翰守,可以使用from...import 的方式
import 模塊名是一次性將模塊中所有工具全部導(dǎo)入孵奶,并且通過模塊名/別名訪問
from 模塊名1 import 工具名
導(dǎo)入之后可以直接使用模塊提供的工具--全局變量、函數(shù)蜡峰、類
注:如果兩個(gè)模塊了袁,存在同名的函數(shù),后導(dǎo)入模塊的函數(shù)會(huì)覆蓋先導(dǎo)入模塊的函數(shù)
從模塊中導(dǎo)入所有工具(知道)
from...import *
在導(dǎo)入模塊文件時(shí)湿颅,文件中所有沒有縮進(jìn)的代碼都會(huì)被執(zhí)行一遍
name 屬性可以做到载绿,測(cè)試模塊的代碼只在測(cè)試情況下被運(yùn)行,而在被導(dǎo)入時(shí)不會(huì)執(zhí)行
name是python的內(nèi)置屬性肖爵,記錄著一個(gè)字符串
如果是被其它文件導(dǎo)入的卢鹦,name就是文件名
py_17_test_module.py
def say_hello():
print("hello!!!")
def say_hi():
print("hi???")
# 被其它文件導(dǎo)入時(shí),不會(huì)被執(zhí)行
if __name__ == "__main__":
print("小米開發(fā)的模塊")
import py_17_test_module
import py_17_test_module as tm
from py_17_test_module import say_hello
py_17_test_module.say_hello()
tm.say_hi()
say_hello()
# 模塊路徑
print(py_17_test_module.__file__)
print(py_17_test_module.__name__) # py_17_testModule
print(__name__) # __main__
- 包
包是一個(gè)包含了多個(gè)模塊的特殊目錄
目錄下有一個(gè)特殊文件 init.py
包名的命名方式與變量名一致劝堪,小寫字母+_
使用 import 包名 可以一次性導(dǎo)入包中的所有模塊
_init.py
要在外界使用包中的模塊冀自,需要在_init.py中指定對(duì)外界提供的模塊列表
# __init__.py內(nèi)容
from . import py_17_send_message
from . import py_17_receive_message
import py_17_message
py_17_message.py_17_send_message.send("你是??嗎")
txt = py_17_message.py_17_receive_message.receive()
- 發(fā)布模塊(知道)
步驟:
1)創(chuàng)建setup.py文件
from distutils.core import setup
setup(name="xh_message", # 包名
version="1.0.0", # 版本號(hào)
description="發(fā)送和接收消息模塊", # 描述信息
long_description="完整的發(fā)送和接收消息模塊", # 完整的描述信息
author="xiaohan", # 作者
author_email="xiaohan@gamil.com", # 作者郵箱
url="www.xiaohan.com", # 主頁
py_17_message=["py_17_message.py_17_send_message", "py_17_message.py_17_receive_message"]) # 模塊中包含的文件名稱
2)構(gòu)建模塊
終端:$ python3 setup.py build
3)生成發(fā)布?jí)嚎s包
終端:$ python3 setup.py sdist
安裝模塊
$ tar -zxvf py_17_message-1.0.0.tar.gz
$ sudo python3 setup.py install
卸載模塊
直接從安裝目錄將模塊目錄刪除即可
$ cd /usr/local/lib/python3/dist-packages/
$ sudo rm -r py_17_message*
可以通過file內(nèi)置屬性獲取模塊所在路徑
$ ipython3
$ import py_17_message
$ py_17_message.file
- 文件
- 文件的基本操作
函數(shù)/方法 | 說明 |
---|---|
open | 打開文件 并且返回文件操作對(duì)象 |
read | 將文件內(nèi)容讀取到內(nèi)存 |
write | 將指定內(nèi)容寫入文件 |
close | 關(guān)閉文件 |
注:
open: 函數(shù)默認(rèn)以只讀方式打開文件
如果文件存在,返回文件操作對(duì)象
如果文件不存在秒啦,會(huì)拋出異常
read: 方法可以一次性讀入并返回文件的所有內(nèi)容
close: 方法負(fù)責(zé)關(guān)閉文件
try:
file = open("text") # 打開文件(默認(rèn)只讀方式)
text = file.read() # 讀取文件
text2 = file.read() # 已經(jīng)讀取過來熬粗,文件指針在末尾,讀取不到任何內(nèi)容
file.close() # 關(guān)閉文件
print(text)
print(len(text2))
except FileNotFoundError:
print("文件不存在")
except Exception as e:
print("未知錯(cuò)誤 %s" % e)
open方法參數(shù):
1.第一個(gè)參數(shù)是要打開的文件名
2.第二個(gè)參數(shù)是訪問方式
參數(shù) | 說明 |
---|---|
r | 以只讀方式打開余境。文件指針會(huì)放在文件開頭驻呐,如果文件不存在會(huì)拋出異常 |
w | 以只寫方式打開。如果文件存在會(huì)被覆蓋芳来,如果文件不存在含末,創(chuàng)建新文件 |
a | 以追加方式打開。如果文件已存在即舌,文件指針會(huì)方法在文件結(jié)尾佣盒;如果文件不存在,會(huì)創(chuàng)建文件 |
r+ | 以讀寫方式打開顽聂。文件指針會(huì)放在文件開頭肥惭,如果文件不存在會(huì)拋出異常 |
w+ | 以讀寫方式打開盯仪。如果文件存在會(huì)被覆蓋,如果文件不存在蜜葱,創(chuàng)建新文件 |
a+ | 以讀寫方式打開全景。如果文件已存在,文件指針會(huì)方法在文件結(jié)尾牵囤;如果文件不存在爸黄,會(huì)創(chuàng)建文件 |
file = open("text", "a")
file.write("hello")
file.close()
file = open("text")
print(file.read())
file.close()
- 按行讀取文件內(nèi)容
readline 方法可以一次讀取一行內(nèi)容
方法執(zhí)行后,會(huì)把文件指針移動(dòng)到下一行奔浅,準(zhǔn)備再次讀取
# 讀取大文件
file = open("text")
while True:
text = file.readline()
if not text:
break
print(text, end="")
file.close()
- 文件指針(知道)
文件指針 標(biāo)記從哪個(gè)位置開始讀取數(shù)據(jù)
第一次打開文件時(shí)馆纳,通常文件指針會(huì)指向文件的開始位置
當(dāng)執(zhí)行了read方法后,文件指針會(huì)移動(dòng)到文件內(nèi)容的末尾 - 復(fù)制文件
# 小文件復(fù)制
file_read = open("text")
file_write = open("text[副本]", "w")
text = file_read.read()
file_write.write(text)
file_read.close()
file_write.close()
file = open("text[副本]")
print(file.read())
# 大文件復(fù)制
file_read = open("text")
file_write = open("text[副本]", "w")
while True:
text = file_read.readline()
if not text:
break
file_write.write(text)
file_read.close()
file_write.close()
file = open("text[副本]")
print(file.read())
- 文件\目錄的常用管理操作
需要導(dǎo)入os模塊
文件操作:
方法名 | 說明 | 示例 |
---|---|---|
rename | 重命名文件 | os.rename(源文件名, 目標(biāo)文件名) |
remove | 刪除文件 | os.remove(文件名) |
path.isfile | 判斷是否是文件 | os.path.isfile(路徑) |
目錄操作:
方法名 | 說明 | 示例 |
---|---|---|
listdir | 目錄列表 | os.listdir(目錄名) |
mkdir | 創(chuàng)建目錄 | os.mkdir(目錄名) |
rmdir | 刪除目錄 | os.rmdir(目錄名) |
getcwd | 獲取當(dāng)前目錄 | os.getcwd() |
chdir | 修改工作目錄 | os.chdir(目標(biāo)目錄) |
path.isdir | 判斷是否是目錄 | os.path.isdir(路徑) |
print(os.getcwd())
# os.mkdir("測(cè)試")
os.remove(os.getcwd() + "/text[副本]")
-
eval
eval函數(shù) 可以將字符串當(dāng)成有效的表達(dá)式來求值汹桦,并返回計(jì)算結(jié)果
注:開發(fā)時(shí)鲁驶,不要使用eval直接轉(zhuǎn)換input的結(jié)果
# 基本數(shù)學(xué)計(jì)算
eval("1 + 1") # 2
# 字符串重復(fù)
eval("'+' * 10") # ++++++++++
# 字符串轉(zhuǎn)列表
type(eval("[1,2,3,4]")) # <class 'list'>
# 字符串轉(zhuǎn)字典
type(eval("{'name':'xiaolan', 'age':'16'}")) # <class 'dict'>
str = input("請(qǐng)輸入算數(shù)題:")
print(eval(str))
"""
__import__('os').system('ls')
# 等價(jià)代碼
import os
os.system("終端命令")
執(zhí)行成功,返回0
執(zhí)行失敗舞骆,返回錯(cuò)誤信息
"""
eval("__import__('os').system('ls')")