最近把《Python编程轻松进阶》看完了,看得过程中顺便整理了一些自己觉得比较重要的点,分享出来,共同进步!
import django
django.__version__
或者使用r’路径名’的形式
>>> from pathlib import Path
>>> Path('spam') / 'bacon' / 'eggs'
WindowsPath('spam/bacon/eggs')
获取主目录
# 获取主目录
Path.home()
# 获取当前目录
Path.cwd()
os.getcwd()
# 更改当前目录
os.chdir('路径名')
.\ 指代当前目录,…\ 指代父目录
如果文件名包含空格,需要用""括起来——cd “my path”
xx /?用于呈现xx命令的相关信息
python -c用于运行无需保留的python代码
python -c “print(‘Hello World’)”
查询指定函数的输出
python -c "help(len)"
运行指定版本的python
py -3.6 -c "import sys;print(sys.version)"
用于在python程序内运行shell命令(对应书中第23页)
命令行输入doskey/history可以查看命令历史记录
*用于匹配任意数量的字符,?用于匹配任何单个字符
dir *.py——查看当前目录下的所有.py文件
Tips:多行代表上面为windows命令,下面为linux命令
显示当前目录以及子目录下的文件
dir /s [文件名]
find . -name [文件名]
copy [源文件] [目标文件]
cp [源文件] [目标文件]
move [源文件] [目标文件]
mv [源文件] [目标文件]
ren [文件/文件夹] [新名称]
mv [文件/文件夹] [新名称]
del 不会删除任何子文件夹中的文件
# 对文件夹用,仅删除文件
del [文件/文件夹]
# 删除文件夹以及其中的文件
rd /s /q [文件夹] # windows
rm -r [文件夹] # linux
# 仅删除文件夹,且必须保证里面是空的
rd [源文件夹] # windows
rmdir [源文件夹] # linux
md [新文件夹]
mkdir [新文件夹]
where [程序名]
which [程序名]
cls
clear
查看环境变量列表
set
查看单个环境变量的值
echo %HOMEPATH%
echo $HOME
修改当前终端窗口的环境变量(仅在当前窗口有效)
path [文件夹路径];%PATH%
PATH=[文件夹路径]:$PATH
永久修改系统PATH变量(需要管理员身份运行命令行)
setx /M PATH "[文件夹路径];%PATH%" # windows
export [文件夹路径];%PATH% # linux,修改.bashrc文件
import logging
logging.basicConfig(filename='logging_filename.txt',
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug('This is a log message')
import timeit
print(timeit.timeit('a=42;b=101;a,b=b,a;'))
# 测试生成1千万个随机数要多久
print(timeit.timeit('random.randint(1,100)','import random', number=10000000))
with open会自动调用close
with open() as filename:
filename.write()
dict_test = {'a': 1}
dict_test.setdefault('b', 0)
dict_test['b'] += 1
需要对任意键设置默认值,推荐使用collections.defaultdict
from collections import defaultdict
dict_test = defaultdict(int)
==判断值是否相同
is判断身份是否相同,x is y 相当于id(x) == id(y)
class语句创建自定义数据类型时,只要实现__iter__和__next__两个特殊方法,就能用for循环遍历
SDK是指软件开发套件(software development kit, SDK),包括代码库、文档和软件工具
Python的赋值是复制了对象的引用,而非对象本身
如果想复制对象本身,需要用copy.copy()或者copy.deepcopy()
import copy
bacon = [1, 2, 3]
ham = copy.copy(bacon)
# 注意,如果列表中嵌套了列表,那么copy()不会复制嵌套列表的本身,因此推荐使用deepcopy()
bacon = [[1, 2], [3, 4]]
ham = copy.deepcopy(bacon)
字符串是不可变对象,每次修改字符串相当于新建了一个对象
因此循环中对字符串进行连接时,可以考虑将字符串append到列表中,最后对列表进行’'.join()操作,速度会快很多
书中P133
False == False in [False]
# 相当于 (False == False) and (False in [False]),返回True
单下划线开头的变量、函数或方法代表伪私有,双下划线代表真正的私有
class Product:
def __init__(self, price):
self.price = price
@property
def price(self):
return self.__price
# 不设置setter表示Price是一个只读属性
@price.setter
def price(self, value):
if value < 0:
raise ValueError("Price cannot be negative.")
self.__price = value
from abc import ABC, abstractmethod
class Stream(ABC):
@abstractmethod
def read(self):
pass
class MemoryStream(Stream):
pass
stream = Stream() # 会报错,抽象基类不准实例化
memory_stream = MemoryStream() # 会报错,因为子类没有实现read这个抽象方法
class Text(str):
def duplicate(self):
return self + self
class TrackableList(list):
def append(self, __object):
print("Append called")
super().append(__object)
lst = TrackableList()
lst.append(1)
text = Text("Python")
print(text.duplicate())
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p1 = Point(x=1, y=2)
p2 = Point(x=1, y=2)
print(p1 == p2) # True
p1.x = 10 # 会报错,不能设置属性的值
from pathlib import Path
path = Path("foo/__init__.py")
path.exists()
path.is_file()
path.is_dir()
print(path.name) # 返回文件名
print(path.stem) # 返回文件前缀
print(path.suffix) # 返回文件后缀
print(path.parent)
# 修改文件名
path = path.with_name("foo.txt")
print(path)
# 修改path后缀
path = path.with_suffix(".py")
print(path)
from zipfile import ZipFile
with ZipFile("files.zip") as zip:
print(zip.namelist())
zip.extractall("extract") # 解压到指定目录
Optional[str]代替Union[str, None]
git log --oneline
git log --oneline -n 3
一旦运行了,就不能撤销这个操作
git restore [文件名]
git add之后,如果想将其从暂存区中移除
git restore --staged [文件名]
其中3是要回滚的提交数量
git revert -n HEAD~3..HEAD
回滚完这个文件之后,要add + commit
git checkout [commit hash] -- [文件名]
git remote add origin https://github.com/williamklzz/wizcoin.git
git push -u origin master
第十三章 性能测量和大O算法分析
用于测量程序的运行时间和程序内各个函数调用消耗的时间——Page 206
import time, cProfile
def add_up_numbers():
total = 0
for i in range(1, 1000001):
total += i
cProfile.run('add_up_numbers()')
>> type(42)
>>
>> type(42).__qualname__ # 使结果更可读,常用来覆盖__repr__()方法
>> 'int'
>> isinstance(42, (int, str, bool)) # 检查42是否是3种类型的其中一种
>> True
类特性是从属于类的变量,所有类对象共享这个特性(类特性很少使用)
from tictactoe_with_OOP import *
>> print(HybridBoard.mro()) # 多继承时获取类方法的调用顺序
>> [<class 'tictactoe_with_OOP.HybridBoard'>, <class 'tictactoe_with_OOP.HintBoard'>, <class 'tictactoe_with_OOP.MiniBoard'>, <class 'tictactoe_with_OOP.TTTBoard'>, <class 'object'>]
# 当我希望每次访问这个特性时,使用赋值语句修改或del删除时,都能运行一段代码
# _some_attribute被称为幕后变量,getter、setter、deleter应该总是作用于幕后变量
# some_attribute是属性
class ClassWithProperties:
def __init__(self):
self.some_attribute = 'some initial value'
@property
def some_attribute(self): # 这是getter方法
return self._some_attribute
@some_attribute.setter
def some_attribute(self, value): # 这是setter方法
self._some_attribute = value
@some_attribute.deleter
def some_attribute(self): # 这是deleter方法
del self._some_attribute
obj = ClassWithProperties()
print(obj.some_attribute)
obj.some_attribute = 'change value'
print(obj.some_attribute)
del obj.some_attribute
# 最佳实践,当WizCoin类被误用时抛出异常,如果抛出了其他异常,说明不是使用的问题,而是类本身的问题
# value.__class__相当于type(value),.__qualname__可以省去class,让输出更简洁
class WizCoinException(Exception):
"""当wizcoin模块被错误使用时,抛出此错误"""
pass
class WizCoin:
def __init__(self, galleons: int, sickles: int, knuts: int):
self.galleons = galleons
self.sickles = sickles
self.knuts = knuts
@property
def galleons(self):
return self._galleons
@galleons.setter
def galleons(self, value):
if not isinstance(value, int):
raise WizCoinException(
f'galleons attr must be set to an int, not a {value.__class__.__qualname__}'
)
if value < 0:
raise WizCoinException(
f'galleons attr must be a positive int, not {value.__class__.__qualname__}'
)
self._galleons = value
# 通过添加property可以让属性变为只读属性
@property
def value(self) -> int:
return (self.galleons * 17 * 29) + (self.sickles * 29) + self.knuts
def weight_in_grams(self) -> float:
"""返回硬币的重量,单位为克"""
return self.galleons * 31.103 + self.sickles * 11.34 + self.knuts * 5.0
# __repr__和__str__
class WizCoin:
--snip--
def __repr__(self):
"""返回一个可以重新创建该对象的表达式的字符串"""
return f'{self.__class__.__qualname__}{self.galleons, self.sickles, self.knuts}'
def __str__(self):
"""返回一个可以重新创建该对象的表达式的字符串"""
return f'{self.galleons}g, {self.sickles}s, {self.knuts}k'
不应该在数值魔术方法里改变对象本身,而是应该创建一个新对象
class WizCoin:
--snip--
def __add__(self, other):
"""将两个WizCoin对象中的硬币数量相加"""
if not isinstance(other, WizCoin):
return NotImplemented # NotImplemented 是一个信号,表示某个操作或方法尚未实现或不支持当前的操作数类型
return WizCoin(
self.galleons + other.galleons,
self.sickles + other.sickles,
self.knuts + other.knuts,
)
def __mul__(self, other: int) -> 'WizCoin':
"""将硬币的数量乘以一个非负整数"""
if not isinstance(other, int):
return NotImplemented
if other < 0:
# 不能乘复数
raise WizCoinException('cannot multiply with negative integers')
return WizCoin(self.galleons * other, self.sickles * other, self.knuts * other)
# 如果符合交换律,可以直接调用__mul__方法
def __rmul__(self, other):
"""反射数值魔术方法,将硬币乘以非负整数"""
return self.__mul__(other)
当对象在数学运算符的左边时,Python调用数值魔术方法,而当对象在数学运算符的右边时,Python调用反射数值魔术方法
# 如果不写__rmul__方法
>> wiz_coin = WizCoin(5, 10, 10)
>> wiz_coin * 10 # 正常乘
>> 10 * wiz_coin # 会报错,TypeError: unsupported operand type(s) for *: 'int' and 'WizCoin'
增强赋值运算符(+=、*=)是原地修改对象
class WizCoin:
--snip--
def __iadd__(self, other: 'WizCoin'):
"""将另一个WizCoin对象加到当前对象中"""
if not isinstance(other, WizCoin):
return NotImplemented
# 原地修改self
self.galleons += other.galleons
self.sickles += other.sickles
self.knuts += other.knuts
return self # 原地魔术方法大多数情况下返回self
def __imul__(self, other: int):
"""将硬币的数量乘以一个非负整数"""
if not isinstance(other, int):
return NotImplemented
if other < 0:
return WizCoinException('cannot multiply with negative integers')
self.galleons *= other
self.sickles *= other
self.knuts *= other
return self