Python(持续学习ing)
长期置顶:
基础教程: http://www.cnblogs.com/dahu-daqing/p/6629577.html
基础教程: http://www.cnblogs.com/linhaifeng/p/7278389.html
爬虫教程: http://www.cnblogs.com/linhaifeng/p/8241221.html
2018-02-07
socket
- https://www.cnblogs.com/alex3714/articles/5830365.html
- socket.SOCK_RAW 可用于 DDoS 攻击
简单 socket 例子(需要先启动服务端)
- 客户端
# Author:Freeman
import socket
client = socket.socket() # 声明 socket 类型,同时生成socket连接对象,参数没填,但是有默认参数
client.connect(("localhost", 6969))
client.send(b"Hello World!") #py3 不再允许字符串,需要 bytes 类型,bytes类型只能接受ASCII码,因此这里如果想要输入汉字:
# client.send("你好,世界!".encode("utf-8")) # 接受时需要 decode 解码为 Unicode
data = client.recv(1024) # 最多接收1024个字节
print("recv:", data)
client.close()
- 服务端
# Author:Freeman
import socket
server = socket.socket()
server.bind(("localhost", 6969)) # 绑定要监听的端口
server.listen() # 监听
print("准备接收信息")
conn, addr = server.accept() # 服务端需要等信息传进来
print(conn)
# conn:就是客户端连过来,而在服务器端为其生成的一个实例
# <socket.socket fd=484, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969)
print(addr) # IP + 随机端口
print("接收信息")
data = conn.recv(1024)
print("recv:", data)
conn.send(data.upper())
server.close()
- 实现类似接打电话的过程,A与B通话,这时C给A打来电话时先等待,等到A与B断开之后再接入C
- 操作过程:
1.先启动服务端
2.启动客户端,并在客户端输入文字:"客户端1"
3.再启动客户端,在新客户端输入文字:“客户端2”
4.断开客户端1(注意,不是红色方块,是下面的红叉),查看 server 结果
# 服务端
import socket
server = socket.socket()
server.bind(("localhost", 6969)) # 绑定要监听的端口
server.listen() # 监听
print("准备接收信息")
while True:
conn, addr = server.accept() # 服务端需要等信息传进来
while True:
data = conn.recv(1024)
if not data:
print("客户端断开")
break
print("recv:", data.decode())
conn.send(data.upper()) # upper() 转大写.将收到的数据转换为大写发送回客户端
server.close()
# 客户端
import socket
client = socket.socket() # 声明 socket 类型,同时生成socket连接对象
client.connect(("localhost", 6969))
while True:
msg = input(">>:").strip()
# client.send(b"Hello World!")
client.send(msg.encode("utf-8"))
data = client.recv(1024) # 接收1024个字节
print("recv:", data.decode())
client.close()
2018-02-06
# Author:Gatling
class Person(object):
# hahahaha
'''描述信息'''
def __init__(self, name):
self.name = name
# lalalala
print(Person.__doc__) # 描述信息
-
__new__
是 用来调用__init__
反射
异常处理
2018-02-05
静态方法
- @staticmethod:这玩意也是个装饰器,必须写在类中的函数,除此之外与类没什么关系,定义时有什么参数就得传什么参数,跟函数一样。在静态方法里访问不了类或实例中的任何属性和方法
类方法
- @classmethod:只能调用 class 自身的变量,无法访问实例变量。例如一个类自身有name 属性,它的实例也具有 name 属性,通常是先调用实例的name,但如果想强行调用 类 的 name 就可以用到了
属性方法
- @property:把一个方法变成静态属性,调用时不能再添加括号
# Author:Gatling
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.__food = None
@property
def eat(self):
print("%s is %s years old,eating %s" % (self.name, self.age, self.__food))
@eat.setter # 传参数
def eat(self, food):
print("set to food:", food)
self.__food = food
@eat.deleter
def eat(self):
del self.__food
print("已删除")
Freeman = Person("Freeman", 18)
Freeman.eat
Freeman.eat = "包子"
Freeman.eat
del Freeman.eat
Freeman.eat
# Freeman is 18 years old,eating None
# set to food: 包子
# Freeman is 18 years old,eating 包子
# 已删除
# Traceback (most recent call last):
# File "D:/ForPython/爬虫.py", line 29, in <module>
# Freeman.eat
# File "D:/ForPython/爬虫.py", line 10, in eat
# print("%s is %s years old,eating %s" % (self.name, self.age, self.__food))
# AttributeError: 'Person' object has no attribute '_Person__food'
2018-02-04
面向对象
# 假设创建一个CS游戏:
# 有角色
# 射击
# 中枪
# 买枪
class Role(object):
# 构造函数中的每个属性在新实例化一个对象的时候都会创建一份
# 而方法只在 Role 中,不会随着新创建实例化对象而创建,每次调用的时候实际上是访问 Role 这个 class 中的方法
def __init__(self, name, role, weapon, life_value=100, money=15000):
# 构造函数
# 在实例化时做一些类的初始化的工作
# self 用于在实例化时传入'实例变量(静态属性)'(就是后面的 r1,r2)
# self 的作用域就是 实例变量本身
# Role(r1,..,..,..) 通过这样的方式告诉 Role 它的'实例变量'是 r1
self.name = name
self.role = role
self.weapon = weapon
# self.life_value = life_value
self.__life_value = life_value # 私有属性
self.money = money
def __del__(self):
# 析构函数:在实例释放或销毁的时候自动执行的
# 通常用于做一些收尾工作,如关闭数据库连接或之前打开的临时文件
print("%s 触发析构函数" % self.name)
def show_status(self):
# 用于访问私有属性的函数
# 私有属性在外面无法直接访问,因此只需要在内部定义一个可以在外部调用的方法,然后在外面调用即可
print("通过定义 show_status() 访问到了私有属性 __life_value:%s" % self.__life_value)
def shot(self): # 动态属性
# 为什么这里有个 self
# 为了告诉这个函数,'谁'调用了这个方法
# 这里面的'谁'就是'实例化名',也就是r1,r2
# r1.shot() == Role.shot(r1)
print("shooting...")
def got_shot(self):
print("ah...,I got shot...")
def buy_gun(self, gun_name):
print("%s just bought %s" % (self.name, gun_name))
r1 = Role('Alex', 'police', 'AK47') # 实例化(初始化一个类,造了一个对象)
r2 = Role('Jack', 'terrorist', 'B22')
r1.buy_gun("Gatling") # Alex just bought Gatling
# del r1 # 删除 r1
# 补充个垃圾回收机制和 __del__ 析构函数
# 进行这个操作后,r1 变量被删除,但 r1 所引用的内存还存在
# Python 通过垃圾回收机制定期循环内存,发现 r1 引用的内存地址还在,但 r1 已经没了
# 因此会认定 r1 内存地址已经没有用了,随即进行删除
# __del__ 析构函数就在此时触发
r2.buy_gun(("Gatling"))
# print(r1.__life_value) # 报错
r1.show_status()
# Alex just bought Gatling
# Jack just bought Gatling
# 通过定义 show_status() 访问到了私有属性 __life_value:100
# Alex 触发析构函数
# Jack 触发析构函数
继承
class SchoolMember(object):
members = 0 # 初始学校人数为0
def __init__(self, name, age):
self.name = name
self.age = age
def tell(self):
pass
def enroll(self):
'''注册'''
SchoolMember.members += 1
print("\033[32;1mnew member [%s] is enrolled,now there are [%s] members.\033[0m " % (
self.name, SchoolMember.members))
def __del__(self):
'''析构方法'''
print("\033[31;1mmember [%s] is dead!\033[0m" % self.name)
class Teacher(SchoolMember):
def __init__(self, name, age, course, salary):
# SchoolMember.__init__(self, name, age)
super(Teacher, self).__init__(name, age) # 与上面一样,在子类中重构父类的方法
self.course = course
self.salary = salary
self.enroll()
def teaching(self):
'''讲课方法'''
print("Teacher [%s] is teaching [%s] for class [%s]" % (self.name, self.course, 's12'))
def tell(self):
'''自我介绍方法'''
msg = '''Hi, my name is [%s], works for [%s] as a [%s] teacher !''' % (self.name, 'Oldboy', self.course)
print(msg)
class Student(SchoolMember):
def __init__(self, name, age, grade, sid):
super(Student, self).__init__(name, age)
self.grade = grade
self.sid = sid
self.enroll()
def tell(self):
'''自我介绍方法'''
msg = '''Hi, my name is [%s], I'm studying [%s] in [%s]!''' % (self.name, self.grade, 'Oldboy')
print(msg)
if __name__ == '__main__':
t1 = Teacher("Alex", 22, 'Python', 20000)
t2 = Teacher("TengLan", 29, 'Linux', 3000)
s1 = Student("Qinghua", 24, "Python S12", 1483)
s2 = Student("SanJiang", 26, "Python S12", 1484)
t1.teaching()
t2.teaching()
t1.tell()
-
继承策略:
D继承BC;B、C继承A
1.广度优先(Python3 默认继承方式):D - B - C - A
2.深度优先(Python2 经典类按深度优先,新式类按广度优先): D - B - A,D - C - A
广度优先 - 继承
class A(object): # class A: 经典类
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
class C(A):
def __init__(self):
print("C")
class D(B,C):
pass
D() # B
- 多态:为了实现接口的重用,一个接口,多种实现
# Author:Gatling
class Animal(object):
def __init__(self, name): # Constructor of the class
self.name = name
def talk(self): # Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
print('%s: 喵喵喵!' % self.name)
class Dog(Animal):
def talk(self):
print('%s: 汪!汪!汪!' % self.name)
def func(obj): # 一个接口,多种形态
obj.talk()
c1 = Cat('小晴')
d1 = Dog('李磊')
func(c1)
func(d1)
2018-02-03
XML 模块
import xml.etree.ElementTree as ET
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
# 遍历xml文档
for child in root:
print(child.tag, child.attrib)
for i in child:
print(i.tag, i.text)
# 只遍历year 节点
for node in root.iter('year'):
print(node.tag, node.text)
- 修改 + 删除
import xml.etree.ElementTree as ET
tree = ET.parse("xmltest.xml")
root = tree.getroot()
#修改
for node in root.iter('year'): # 找到 year
new_year = int(node.text) + 1
node.text = str(new_year)
node.set("updated","yes") # 添加属性
tree.write("xmltest.xml")
#删除node
for country in root.findall('country'): # 找到所有的 country
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country) # 删除 node
tree.write('output.xml')
- 查找
import xml.etree.ElementTree as ET
new_xml = ET.Element("namelist") # Element 根节点
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) # SubElement 子节点
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
et = ET.ElementTree(new_xml) # 生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True) # xml_declaration 声明这是 xml 格式的
ET.dump(new_xml) # 打印生成的格式
ConfigParser 模块:解析配置文件
hashlib 模块:加密相关
hmac 模块:加密进阶版
tips
- ctrl+shift+n 查找文件
- ctrl+n
re 模块:正则
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a']
'+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?' 匹配前一个字符1次或0次
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
'\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z' 匹配字符结尾,同$
'\d' 匹配数字0-9
'\D' 匹配非数字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
-
'(?P<name>...)'
分组匹配 :配合 groupdict() 实现为匹配的字符加上 key 键
re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")
# 结果
{'province': '3714', 'city': '81', 'birthday': '1993'}
- 一些常用的方法
re.match 从头开始匹配(只匹配第一个)
re.search 匹配包含(只匹配第一个)
re.findall 把所有匹配到的字符放到以列表中的元素返回 ,匹配不到是空数组 [] , ['']是匹配到了
re.split 以匹配到的字符当做列表分隔符
>>> re.split("\d+","a1b22c333d4444e")
['a', 'b', 'c', 'd', 'e']
>>> re.split("\d","a1b22c333d4444e")
['a', 'b', '', 'c', '', '', 'd', '', '', '', 'e']
re.sub 匹配字符并替换
- res = re.match()
res.group():匹配到的字符串
2018-02-02
标准库 - shutil 模块
# Author:Freeman
import shutil
# f1 = open('note', encoding="utf-8") # 有这个文件
# f2 = open('note2', 'w', encoding='utf-8') # 没有这个文件,创建一个
# shutil.copyfileobj(f1, f2) # 把 f1 的内容复制一份到 f2
shutil.copyfile('note2', 'note3') # 直接复制一个文件的副本(note3)
# shutil.copystat(src, dst) # 拷贝:mode bits,atime,mtime,flags
# shutil.copy() # 拷贝文件和权限
# shutil.copy2() # 拷贝文件和状态信息
# shutil.copytree(原目录,目标目录) # 完整的拷贝目录
# shutil.rmtree() # 删除目录
# shutil.move() # 移动文件
# shutil.make_archive("压缩", 'zip', r'D:\ForPython\2018-1-30') # 创建压缩包并返回路径
shelve 模块
2018-02-01
标准库 - random
import random
random.randint(1,10) # 随机 [1,10] 的整数
random.randrange(1,10) # 随机 (1,10) 的整数
random.choice(seq)
标准库 - os
- 常用方法
# Author:Freeman
import os
print(os.getcwd()) # 当前路径:D:\ForPython\2018-02-01
os.chdir(r"D:\ForPython\2018-02-01") # 切换路径:命令行中为了避免转义,需要两个\\ ,也可以 r'D:\ForPython'
print(os.getcwd()) # D:\ForPython
print(os.curdir) # 当前目录 .
print(os.pardir) # 上一级目录 ..
os.makedirs(r'a\b\c') # 递归创建目录(可以指定任意路径)
os.removedirs(r'a\b\c') # 递归删除目录
# 删除目录(主要用于清理空目录):
# 1.检查c是否为空,是则删除c
# 2.检查b是否为空,是则删除b
# 3.检查a是否为空,是则删除a
os.mkdir(r"E:\abc") # 创建目录(可以指定任意路径)
os.rmdir(r"E:\abc") # 删除单个目录
print(os.listdir()) # 返回当前目录下的文件组成的一个 list(包括隐藏文件)
# os.rename(r'D:\ForPython\2018-02-01\level2_change', r'D:\ForPython\2018-1-31\level2') # 把参数1的文件转移到参数2,支持改名
os.stat("os.py") # 获取文件 / 目录信息
os.environ # 查看环境变量
os.name # 当前系统名
os.path.abspath()
os.path.split(r"D:\a\b\c\d.txt") # 返回:('D:\a\b\c','d.txt') (不考虑文件是否存在)
os.path.basename(r"D:\a\b\c.txt") # 返回:'c.txt' (不考虑文件是否存在)
os.path.exists() # 判断路径是否存在
os.path.isabs() # 是否为绝对路径(Windows 以盘符开始,Linux以 / 开始)
os.path.isfile() # 是否为一个文件
os.path.isdir() # 是否为一个目录
os.path.join(r'C:',r'\a.txt') # 'C:\a.txt'
os.path.getatime() # 文件或目录的最后存取时间
os.path.getmtime() # 文件或目录的最后修改时间
- 特别说明:由于 Windows 和 Linux 操作系统的路径规范不一致,
Name | Windows | Linux |
---|---|---|
路径斜杠 | \ | / |
换行 | \r\n | \n |
文件路径分隔符 | ; | : |
-
os.system(command)
os.system()
标准库 - sys 模块
tips
折叠面板和自带命令行2018-1-31
标准库 - time 模块
- 忘了有什么方法可以使用 help()
- 时间戳 / Structure_time(tuple 格式) / 格式化字符串
1.时间戳 => 元祖 localtime(),gmtime()
2.元祖 => 时间戳 mktime()
3.元祖 => 指定字符串时间格式 strftime()
4.指定字符串时间格式 => 元祖 strptime()
5.时间戳=>字符串 asctime([tuple]),ctime([seconds])
# time 具有的方法
time() -- return current time in seconds since the Epoch as a float
clock() -- return CPU time since process start as a float
sleep() -- delay for a number of seconds given as a float
gmtime() -- convert seconds since Epoch to UTC tuple
localtime() -- convert seconds since Epoch to local time tuple
asctime() -- convert time tuple to string
ctime() -- convert time in seconds to string
mktime() -- convert local time tuple to seconds since Epoch
strftime() -- convert time tuple to string according to format specification
strptime() -- parse string to time tuple according to format specification
tzset() -- change the local timezone
- 时间戳格式化为指定格式
# Author:Freeman
import time
Epoch_time = time.time()
time_tuple = time.localtime(Epoch_time)
format_time = time.strftime("%Y-%m-%d %H:%M:%S", time_tuple) # %Y 不是位置对应,%Y 放哪里都是年
print(Epoch_time)
print(time_tuple)
print(format_time)
# 1517414160.0117865
# time.struct_time(tm_year=2018, tm_mon=1, tm_mday=31, tm_hour=23, tm_min=56, tm_sec=0, tm_wday=2, tm_yday=31, tm_isdst=0)
# 2018-01-31 23:56:00
- 时间格式的符号说明
%a 本地(locale)简化星期名称
%A 本地完整星期名称
%b 本地简化月份名称
%B 本地完整月份名称
%c 本地相应的日期和时间表示
%d 一个月中的第几天(01 - 31)
%H 一天中的第几个小时(24小时制,00 - 23)
%I 第几个小时(12小时制,01 - 12)
%j 一年中的第几天(001 - 366)
%m 月份(01 - 12)
%M 分钟数(00 - 59)
%p 本地am或者pm的相应符 一
%S 秒(01 - 61) 二
%U 一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周。 三
%w 一个星期中的第几天(0 - 6,0是星期天) 三
%W 和%U基本相同,不同的是%W以星期一为一个星期的开始。
%x 本地相应日期
%X 本地相应时间
%y 去掉世纪的年份(00 - 99)
%Y 完整的年份
%Z 时区的名字(如果不存在为空字符)
%% ‘%’字符
标准库 - datetime 模块
# Author:Freeman
import datetime
_now = datetime.datetime.now()
_future_day = datetime.datetime.now() + datetime.timedelta(3)
_ago_day = datetime.datetime.now() + datetime.timedelta(-3)
_future_hours = datetime.datetime.now() + datetime.timedelta(hours=3)
_future_minutes = datetime.datetime.now() + datetime.timedelta(minutes=15)
_ago_minutes = datetime.datetime.now() + datetime.timedelta(minutes=-15)
print(_now) # 2018-02-01 00:32:21.502319
print(_future_day) # 2018-02-04 00:32:21.502319
print(_ago_day) # 2018-01-29 00:32:21.502319
print(_future_hours) # 2018-02-01 03:32:21.502319
print(_future_minutes) # 2018-02-01 00:47:21.502319
print(_ago_minutes) # 2018-02-01 00:17:21.502319
关于导入包
- 导入包实际上是导入包内的
__init__.py
文件,因此需要在__init__.py
中进一步导入子包或模块
目录结构
现在想为grandpa.py
导入son.py
,步骤如下:
# grandpa.py
import level2
# level2 包内的 __init.py__
from . import level3
# level3 包内的 __init.py__
from . import son
# son.py
text = "调用成功!"
# grandpa.py 中调用 son 中的方法
print(level2.level3.son.text) # 调用成功!
tips
-
Structure 界面可以显示当前文件的变量和函数,打开方法:
1.alt+7
2.view - Tool Windows - Structure
Structure -
在 Project 视图中,让文件显示包括的方法
Show Members -
import module_A
再通过module_A.func
调用模块内的func
方法是先找到module_A
再引用func
方法,如果引用 N 次func
,则在找module_A
上会浪费掉大量的时间,因此针对这种情况,如果只引用func
方法,则使用from module_A import func
会减少找文件的时间
2018-1-30
模块
- 定义:本质就是 .py 结尾的 Python 文件,目的就是为了实现某个功能(文件名为
test.py 则模块名为 test) - 导入模块方法
# 第一种导入
import module1,module2 # 导入多个模块
module1.func() # 调用
# 第二种导入
from module import func # 导入所有变量和函数(不建议,重名)
from module import func1,func2,func3
func() # 调用 不能 module1.func(),因为导入的是模块里的所有内容
# 第三种导入
from module import func as another_func # 起个别名
another_func() # 调用
# 第四种导入
from . import func # 从当前目录下导入 func
- import 本质:相当于把 A模块内所有的代码统一赋给变量 A
- from module import func:相当于直接把 module 中的 func 代码赋给一个 func 变量
- 包的定义:从逻辑上组织模块,本质就是一个目录(必须带有一个 init.py 的文件)
- 导入包文件实际上就是执行包内的
__init__.py
文件(只是当前包内的__init__py
)
导入包
2018-1-28
Python 内置方法
- abs(): 绝对值
- all():全真反真
# Author:Freeman
list = [0, 1, 2, 3]
print(all(list)) # True
- any():有真反真
- ascii():
- bin():十进制整数转二进制
- bool():布尔值
- bytearray():返回 ascii 码,并且可通过为元素赋不同的 ascii 码值来改变(常规的str和二进制是无法在原对象上改变的,都是创建一个副本)
# Author:Freeman
a = bytes("abcde", encoding="utf-8")
b = bytearray("abcde", encoding="utf-8")
print(a.capitalize(), a)
print(b[0]) # ascii 码
b[0] = 98
print(b)
# b'Abcde' b'abcde'
# 97
# bytearray(b'bbcde')
- callable():判断是否可调用,例如函数就可通过 ()调用,list 没法调用
- chr():传入 ascii 码值,返回对应符号
- ord():传入 符号,返回 ascii 值
- compile():跟 js 的 eval 差不多
- dir(对象) 查看对象可以调用的方法
- divmod():返回商和余数
- eval():
- exec():
- filter():过滤
# Author:Freeman
express = lambda n: n > 5
res = filter(express, range(10))
print(type(res)) # <class 'filter'>
for i in res:
print(i)
# <class 'filter'>
# 6
# 7
# 8
# 9
- map():
# Author:Freeman
express = lambda n: n * n
res = map(express, range(5))
print(type(res)) # <class 'map'>
for i in res:
print(i)
# <class 'map'>
# 0
# 1
# 4
# 9
# 16
- reduce():意思就是对sequence连续使用function, 如果不给出initial, 则第一次调用传递sequence的两个元素, 以后把前一次调用的结果和sequence的下一个元素传递给function. 如果给出initial, 则第一次传递initial和sequence的第一个元素给function.
# Author:Freeman
import functools
express = lambda x, y: x + y
res = functools.reduce(express, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 计算过程 ((((((((0 + 1) + 2) + 3) + 4) + 5) + 6) + 7) + 8) + 9
print(res)
# 45
- lambda表达式:
lambda n:3 if n<4 else n
# n 小于 4 就是 3,否则就是 n
-
frozenset([iterable]):不可变集合,用了之后集合就不能进行添加删除
-
globals():返回当前文件内所有的全局变量和值的 dict 格式
-
locals():返回当前局部作用于内的变量和值
-
hash():将参数转换为 hash 值,为了方便排序后的 折中查找
-
hex():转成十六进制
-
oct():八进制
-
max():
-
min():
-
pow():幂
-
reversed():反转
-
round():保留几位小数
-
slice():
-
sorted():排序
-
zip():
# Author:Freeman
key = ["a", "b", "c", "d"]
val = [9, 5, 2, 7]
for i in zip(key, val):
print(i)
# ('a', 9)
# ('b', 5)
# ('c', 2)
# ('d', 7)
序列化(dumps) / 反序列化(loads)
- dumps / loads 操作只进行一次,多次 dumps 的确可以存入多个 json 字符串,但没法正确 loads
- json
# Author:Freeman
import json
def sayhi():
print("hello,", name)
jsonObj = {
"name": "kaka",
"age": "18",
# "func":sayhi # 会报错,不支持这种方式
}
f = open("yesterday", "r", encoding="utf-8")
# f.write(json.dumps(jsonObj)) # str
json.loads(f.read()) # dict
- pickle:是以 bytes 类型写入或者读取,因此 open 的方式必须为 wb 或 rb 等二进制读写
# Author:Freeman
import pickle
def sayhi(name):
print("hello,", name)
pickleObj = {
"name": "kaka",
"age": "18",
"func": sayhi
}
f = open("yesterday", "wb")
f.write(pickle.dumps(pickleObj)) # pickle.dump(pickleObj,f) # 效果一样
以上代码存在于文件A,但在另一个文件B中去读 yesterday 这个文件会报错,因为 sayhi 这个函数只是存在于文件A之中,在文件B中是找不到 sayhi 的内存地址,除非在B中定义一个同名的 sayhi 函数
python 建议项目结构
Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README
简要解释一下:
#
# bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
# foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py。
# docs/: 存放一些文档。
# setup.py: 安装、部署、打包的脚本。
# requirements.txt: 存放软件依赖的外部Python包列表。
# README: 项目说明文件。
# 除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。如果你想写一个开源软件,目录该如何组织,可以参考这篇文章。
跨文件调用
-
想从 atm.py 中调用 main.py 的方法
项目结构
# atm.py
# print(__file__) # 相对路径, pycharm 中显示的是绝对路径
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath((__file__))))
# __file__ 代表当前文件
# os.path.abspath 绝对路径 D:\ForPython\atm\bin\atm.py
# os.path.dirname 当前文件所在的目录名,这里向上找了两次
sys.path.append(BASE_DIR) # 添加环境变量
# sys.path 本身返回的是一个当前文件能访问到的路径组成的一个 list,
# 因此只要在这个 list 中添加一个新模块的路径,在当前文件中就可以 import 新模块
# 这里还有个问题,新插入的路径在最后面,如果在之前有重名的模块就不会调用到预期的模块,但由于是 list,可以不采取 append 而是 insert 之类的方法
from conf import settings
from core import main
main.info()
# 你已经成功调取到 main.py 的内容!
# main.py
def info():
print("你已经成功调取到 main.py 的内容!")
2018-1-27
tips
- alt + 鼠标左键可以创建多个光标
生成器 generator
- 为什么要使用生成器?
比如有一个具有几十亿个元素的 list,如果想把 list 赋值给变量 a,会消耗很长的时间,list 也会占用很大的内存。generator 的存在就是为了解决这个问题,先 准备 出一个具有几十亿元素的 generator (相当于告诉内存,我要你先准备一个列表,但你现在不用创建出来,等我需要用到哪个的时候再去找你,到时候你只需要给我我要的东西就可以),但并不占用内存,只有当调用 generator 中具体某个值时,那个值才会存在于内存之中 - generator 只有在调用的时候才生成相应的数据,所以没办法使用切片或者 list 的常规操作
- generator 具有
__next__
方法(Python3.0,2.7为 next()),且只能一个一个的往后找,不能返回,不能跳过
# Author:Freeman
generator = (i for i in range(10))
print(generator)
print(generator.__next__())
print(generator.__next__())
# <generator object <genexpr> at 0x000002E245B288E0>
# 0
# 1
列表生成式
- 常规
# Author:Freeman
a = [i + 2 for i in range(10)]
print(a)
# [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
- 函数
# Author:Freeman
def func(*args):
answer = "哈哈 %s" % args
return answer
a = [func(i) for i in range(10)]
print(a)
生成器 + 异常处理
- yield 用于保存函数的中断状态
# Author:Freeman
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 有 yield 的存在,fib 就已经是一个生成器了,而 b 就是生成器中的元素
a, b = b, a + b
n = n + 1
return "----done----" # 用于捕获错误
g = fib(5)
# 异常捕获
while True:
try:
# x = next(g) # 在 3.0 中这句也好用
x = g.__next__()
print("g:", x)
except StopIteration as e: # 捕获 StopIteration 错误
print("Generator return value:", e.value)
break
# g: 1
# g: 1
# g: 2
# g: 3
# g: 5
# Generator return value: ----done----
- 生成器例子
# Author:Freeman
import time
def consumer(name):
print("[%s]来吃包子了!" % name)
while True:
ab = yield
print("[%s]包子来了,但是[%s]并没有吃到包子" % (ab, name))
c = consumer("大飞哥")
c.__next__() # [大飞哥]来吃包子了!
c.__next__() # [None]包子来了,但是[大飞哥]并没有吃到包子
c.__next__() # [None]包子来了,但是[大飞哥]并没有吃到包子
c.send("韭菜馅") # [韭菜馅]包子来了,但是[大飞哥]并没有吃到包子
c.send("面馅") # [面馅]包子来了,但是[大飞哥]并没有吃到包子
c.__next__() # [None]包子来了,但是[大飞哥]并没有吃到包子
- 生成器例子(协程)
# Author:Freeman
import time
def consumer(name):
print("[%s]来吃包子了!" % name)
while True:
ab = yield
print("[%s]包子来了,但是[%s]并没有吃到包子" % (ab, name))
list = ["韭菜馅", "面馅"]
def producer(name):
c = consumer("A")
c2 = consumer("B")
c.__next__()
c2.__next__()
print("[%s]开始准备做包子啦!" % name)
for i, item in enumerate(list):
time.sleep(1)
print("%s做了两个包子!"%name)
c.send(item)
c2.send(item)
producer("大帅哥")
# [A]来吃包子了! # consumer
# [B]来吃包子了! # consumer
# [大帅哥]开始准备做包子啦! # producer
# [大帅哥]做了两个包子! # producer
# [韭菜馅]包子来了,但是[A]并没有吃到包子 # consumer
# [韭菜馅]包子来了,但是[B]并没有吃到包子 # consumer
# [大帅哥]做了两个包子! # producer
# [面馅]包子来了,但是[A]并没有吃到包子 # consumer
# [面馅]包子来了,但是[B]并没有吃到包子 # consumer
迭代器
- 可直接作用于 for 循环的对象
1.list ,tuple,set,dict,str
2.generator:包括生成器和带 yield 的 generator function
以上两类统称为可迭代对象:Iterable,可以使用 isinstance() 判断一个对象是否为 Iterable 对象 - 迭代器(Iterator):可以被 next() 函数调用并不断返回下一个值的对象
- generator 都是 Iterator 对象,但 list、dict、set 虽然是 Iterable,但却不是 Iterator,可以使用 iter() 方法将 list、dict、set 变为 Iterator
装饰器
- 带参数的装饰器,不是很理解,先放这里吧
# Author:Freeman
import time
user, passwd = "kaka", "123"
def auth(auth_type):
def outer_wrapper(func):
def wrapper(*args, **kwargs):
if auth_type == "local":
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
return func(*args, **kwargs)
else:
exit("\033[31;1mInvalid username or password\033[0m")
elif auth_type == "ldap":
print("搞毛线?")
return wrapper
return outer_wrapper
def index():
print("welcome to index page")
@auth(auth_type="local")
def home():
print("welcome to home page")
return "from home"
@auth(auth_type="ldap")
def bbs():
print("welcome to bbs page")
# index()
# print(home())
home()
# bbs()
2018-1-26
装饰器
- 高阶函数(返回函数地址的函数)+ 嵌套函数
- 下面代码中 timer 就是装饰器,满足了两个条件:
1.不改变 test1 的内容;
2.不改变 test1 的调用方式 - 装饰器作用于紧邻它的第一个函数
# Author:Freeman
import time
def timer(func):
def deco():
start_time = time.time()
func()
end_time = time.time()
print("func run time is %s" % (end_time - start_time))
return deco
@timer # 装饰器,之后直接调用 test1 就是携带装饰器的调用,装饰器作用于紧邻它下面的第一个函数
def test1():
time.sleep(2)
print("this is test1 func")
test1()
# timer(test1)() # 如果不用装饰器,也可以这么写
- 如何携带参数?
# Author:Freeman
import time
def timer(func):
def deco(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print("func run time is %s" % (end_time - start_time))
return deco
@timer
def test1(*args, **kwargs):
time.sleep(2)
print("this is test1 func:", *args, **kwargs)
# timer(test1)()
# test1 = timer(test1) # 不要考虑那些乱七八糟的,timer 执行返回 deco 地址,test1 就是 deco 地址,再进一步说,调用 test1 就是调用 deco
test1("kaka", {"dict_key": 5})
- 为什么没有返回值 "from home"?该怎么做,为什么?
# Author:Freeman
import time
user, passwd = "kaka", "123"
def auth(func):
def wrapper(*args, **kwargs):
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
func(*args, **kwargs)
else:
exit("\033[31;1mInvalid username or password\033[0m")
return wrapper
def index():
print("welcome to index page")
@auth
def home():
print("welcome to home page")
return "from home" # 为什么这行没有返回?打印结果中的 None 是哪来的?
@auth
def bbs():
print("welcome to bbs page")
index()
print(home())
bbs()
# welcome to index page
# Username:kaka
# Password:123
# User has passed authentication
# welcome to home page
# None # 这是什么鬼?from home 呢?
# Username:
# 解释:
# 如上个例子所言,调用 home 就等于调用 wrapper
# 然而 home 有返回值,装饰器中 wrapper 中的 home() 也的确进行了调用并返回了 from home,但是 wrapper 没有 return
# 可以理解为 wrapper 中已经包含了 home 的返回值 from home ,但是 wrapper 没有把 这个 from home 的结果 return 出来
# 没有 return 语句的函数默认返回值为 None
# 注意:return wrapper 是 auth 的返回值,不是 wrapper 的
2018-1-25
tips
- y=x=1,1一直在内存中,可以通过x,y来找到1的内存地址。使用 del 可以删除 x,y 而1不会被 del 删除,当 1 没有任何引用的时候,Python 内部的定时回收机制会删除 1
装饰器
- 定义:本质是函数,用于装饰其它函数——为其它函数添加附加功能
- 原则:
1.不能修改被装饰函数的源代码
2.不能修改被装饰函数的调用方式 - 通俗的讲,装饰器可以让函数在不知情的情况下发生改变
- 实现装饰器的知识储备:
1.函数即是变量
2.高阶函数:a.把函数名当做一个实参传给另一个函数;b.返回值中包含函数名
3.嵌套函数
高阶函数+嵌套函数 => 装饰器
2018-1-24
- int 是 向0取整
递归
- 必须要有一个明确的结束条件
- 每次进入更深一层的递归时,问题的规模相比上一次递归都应该有所减少
- 递归效率不高,递归次数过多会导致栈溢出
- 做递归用 断点 调试
函数
- 默认参数
# Author:Freeman
def func(x, y, z=3):
print(x)
print(y)
print(z)
func(2, 1, "kk")
# 输出 2,1,kk
- 非固定参数 * + 形参,*args 接收 位置参数 转换成 元祖
# Author:Freeman
def func(*args):
print(args)
print(args[1])
print(len(args))
func(2, 1, "kk")
# (2, 1, 'kk')
# 1
# 3
# Author:Freeman
def dict(name, age=12, *args):
print(name)
print(age)
print(args)
dict(*["lky", "222", "gogogo"])
# lky
# 222
# ('gogogo',)
- 接受字典参数 ** + 形参,两种方式传参,**kwargs 部分只能接收 关键字参数(a=3 这种) 转换成 字典
# Author:Freeman
def dict(**kwargs):
print(kwargs)
dict(name="xxx", age="123", salary="没有") # 第一种
dict(**{"name" : "xxx", "age" : "123", "salary" : "没有"}) # 第二种
# {'name': 'xxx', 'age': '123', 'salary': '没有'}
# {'name': 'xxx', 'age': '123', 'salary': '没有'}
**kwargs 参数组往后放:当关键字参数合法时,不会被当做字典参数
# Author:Freeman
def dict(name, age=12, **kwargs):
print(name)
print(age)
print(kwargs)
dict(name="lky",age="222",key="gogogo")
# lky
# 222
# {'key': 'gogogo'}
- 在局部作用域修改全局变量:global 。避免使用 global 在局部作用于声明全局变量
# Author:Freeman
abc = 12
def change(param=3):
global abc # 这里不能写赋值
abc = 11
print(abc) # 这里不能写赋值
change()
# 11
2018-1-23
编程方式
- 面向对象
核心是 类,定义它的关键字就是 class - 面向过程
过程,def:实际上就是没有返回值的函数,Python 解释器隐式的返回 None。而面向过程的编程方式实际上就是用许多没有返回值的函数组成的一种编程方式。 - 函数式编程
函数, def:有返回值
函数
- 直接传参 / 位置调用
- 位置调用需要与形参一一对应
- 位置调用与关键字调用混用时,应保证位置参数在前,最好别这么混着用
# Author:Freeman
def func(x, y):
print(x)
print(y)
# func(1, 2)
func(y=1, x=2)
输出时间
# Author:Freeman
import time
rule = "%Y-%m-%d %X"
time = time.strftime(rule)
print(time)
# 输出 2018-01-23 23:08:23
2018-1-22
打印系统默认编码
- sys.getdefaultcoding()
ASCII Unicode utf-8 的区别
- 不同国家的编码互相转换都需要先转换成 Unicode:比如中国的GBK编码,需要先解码为 Unicode 再编码成其他国家的编码
有个图不错,去找一下
with
- 无需再写关闭文件语句,with 语句执行完后文件就被关闭
- Python2.7 之后 with 语句可以打开多个文件
- Python 官方书写规范,通过 反斜杠 \ 换行
# Author:Freeman
import sys
with open("yesterday", "r", encoding="utf-8") as f, \
open("yesterday2", "r", encoding="utf-8") as f2:
for i in f:
print(i.strip())
tips
- 为什么需要在代码中关闭文件?
尽管在你关闭程序时,Python 的垃圾回收机制会自动收回打开文件所占用的内存,但如果你打开N多个文件,如果不通过代码关闭文件的占用,则这个文件会一直占用内存。
sys.argv
- sys.argv:
# Author:Freeman
import sys
item = sys.argv
print(item)
print(item[0])
print(item[1])
print(item[2:])
需要在命令行下
- 一个查找并替换文件内容的方法
# Author:Freeman
import sys
f = open("yesterday", "r+", encoding="utf-8")
old_str = sys.argv[1]
new_str = sys.argv[2]
for line in f:
if old_str in line:
line = line.replace(old_str, new_str)
print(line)
yesterday 文件的内容
命令行中执行结果
之前的
快捷键
- ctrl + alt + L 代码格式化
- ctrl + B 跳转到源代码 或者 按住 ctrl+左键
- ctrl + w 逐渐扩选代码块,ctrl + shift + w 反之
- ctrl + / - 展开 / 折叠代码 ,加 shift 就是全部展开 / 折叠
input()
- 导入模块,getpass 在 pycharm 中不好使
- input("123") 中输入的结果会被当做 字符串,转换为数字需要 int(input("123"))
# Author:Liu
import getpass
_username = "lky"
_password = "123"
username = input("name:")
password = getpass.getpass("password:")
if _username == username and _password == password:
print("Welcome {name} login".format(name=username)) # 字符串连接
else:
print("Invalid username or password")
循环 判断 跳出循环
- while,for 都可以搭配 else
# Author:Liu
age_of_oldboy = 56
while True:
guess_age = int(input("guess age:"))
if guess_age == age_of_oldboy:
print("yes ,you got it.")
break
elif guess_age > age_of_oldboy:
print("think smaller...")
else:
print("think bigger!")
range()
- range(开始,结束,步长)
# Author:Liu
for i in range(1, 10, 3):
print(i) # 1,4,7
打断点
image.png模块(库)
-
标准库:直接可用,比如 getpass
-
第三方库:例如 Django
-
文件名避免与库名重复
-
sys 模块
1.sys.path:环境变量
2.sys.argv:当前脚本的相对路径(Pycharm 中由于软件设置,会打印绝对路径)
sys 模块(site-packages 为第三方库存放地址,lib 层为标准库存放地址) -
os 模块:一般用于与系统的交互
1.os.system("dir"):用于直接显示当前文件所在目录的所有文件,之后返回结果,0 代表成功
os.system("dir")
# 一些常用的 os 方法
# Author:Liu
import os
# cmd_res = os.system("dir") # 执行命令,无法保存结果
# cmd_res = os.popen("dir") # 内存对象地址
# cmd_res = os.popen("dir").read() # 读取地址
os.mkdir("new_dir_by_python") # 创建目录
print("-->", cmd_res)
.pyc 是什么?
- .pyc 文件是 Python 的编译后的 字节码文件,它还不是机器码,甚至算不上 “半成品”
- 程序第一次运行后产生 .pyc 文件,下次再运行时就不需要重新编译,直接调用 .pyc 文件
- 当保存了 .pyc 文件之后,对源文件又做了改动,这时 Python 会根据源文件和 .pyc 文件的最后更新时间来判断文件是否经过改动
数据类型
- type() 查看数据类型
- ** 幂
- int 整形 ,long 长整型,float 浮点型,布尔,字符串,bytes 类型
- 视频,音频的二进制传输类型为 bytes
- python3 没有长整形 long
三元运算
result = 值1 if 条件1 else 条件2
十六进制表示法
- 0x 前缀,或者 H 作为后缀
编码和解码
- 需要编码.encode(想要转换成那种编码)
- 需要解码.decode(之前的编码集)
- Python3 中 encode() 之后都会变成 bytes 类型
- 所有的 .decode() 动作都是要解码为 Unicode
切片
- 切片也可以跳着切,[起点:终点:步长]
# Author:Liu
names = ["a", "b", "c", "d"]
print(names[0])
print(names[1:2])
print(names[1:])
print(names[-2:])
names.insert[1,"abc"] # 插入
names[2] = "aaaa" # 替换
del names[1] # 删除 也可以删除变量
names["c"] # 删除
切片
- append():最后添加
- pop([index]):删除,不写参数默认删除最后一个
- insert(位置,需要插入的元素)
- index("xxx") 位置
- count("xxx") 数量
- list.clear() 清空
- copy() 浅拷贝,只复制第一层,是复制,复制完就变成两个独立的 第一层!
# Author:Liu
import copy
names = ["name", ["saving"]]
# 浅copy的三种方式
names2 = copy.copy(names)
names2 = names[:]
names2 = list(names)
# 浅copy的用途 —— 联合账号
names[0] = "husband"
names2[0] = "wife"
names[1][0] = 5000
print(names) #['husband', [5000]]
print(names2) #['wife', [5000]]
- 深拷贝:将数据完全拷贝一份,互不影响,没有引用问题
# Author:Liu
import copy
# 深copy
names = ["a", "b", "b", [1, 2], "c", "d"]
names2 = copy.deepcopy(names)
names2[3][1] = "bbbbb"
print(names[3][1])
元祖(只读列表)
- 不能改的列表
- 只有两个方法,count(),index()
.isdigital()
- .isdigital():纯整数 的字符串,返回:true,false。
enumerate()
- for index,item in enumerate(list) 跟 jQuery 的 each 循环差不多
字符串操作,注意,是字符串的方法
- capitalize():首字母大写
- count():计数
- center():一共 xx 个字符,不够的话用指定字符填充,如果是两边不对等,字符串右侧多一个
# Author:Liu
name = "123"
print(name.center(40, "-"))
# ------------------123-------------------
- encode()
- endswith():字符串以什么结尾
- expendtabs():当字符串中有 \t 时,可在方法内添加 tabsize=12 来替换字符串中的 \t
- find():返回查询字符串的第一个字符的位置
- format():格式化嵌入数据
- format_map():参数传一个 字典
# Author:Liu
name = "My name is {name},I'm {age} years old"
print(name.format(name="kaka", age='2222'))
print(name.format_map({"name":"Dictionary","age":"122"}))
# My name is kaka,I'm 2222 years old
# My name is Dictionary,I'm 122 years old
- index():下标
- inalnum():只包含数字字母的字符串才是 true ,含有其它的符号均为 false
- isalpha():是否只包含纯英文字符(无所谓大小写)
- isdecimal():
- isdigit():是否整数,不支持中文数字,也支持 “壹”
- isidentifier():是否是一个合法的标识符,可以用来检查变量名是否合法
- islower():是否是小写
- isnumeric():是否整数,支持中文数字。注意跟 isdigit() 的对比
- isspace():是否是空格,\t,\n 也是 True
- istitle():所有单词是否首字母大写
- isprintable():tty file,drive file 会返回 False
- isupper():是否大写
- join():print("-".join(["a","b","c"])),拼接
- ljust() / rjust():右侧补位,左侧补位,对应 center()
- lower() / upper():变小写 / 大写
- lstrip() / rstrip() / strip():去掉左边 / 右边 / 两边的空格或回车
1.strip() 可以从两边开始删除指定的字符串
2.创建副本,不改变原字符串 - maketrans():
p = str.maketrans("abcd", "1234") # 重复的话以最后为准,数量必须一样
print("abcd".translate(p))
# 输出:1234
- replace():三个参数,被替换的,用于替换的,个数
- rfind():返回匹配到的结果中,最右侧的结果的位置
- split():str 切割为 list
- splitlines():以 \n 切割
- swapcase():大写变小写,小写变大写
- translate():与 maketrans() 配合使用
- zfill():不够的话前面补0
字典 Dictionary
- 字典是无序的
- key 是唯一的
- 字典的方法:
1.dict.del():删掉一个 key,也可不写参数删除整个字典
2.dict.pop():删掉指定 key,必须写参数
3.dict.popitem():随机删
4.查找 dict["aaa"] 如果参数 key 不存在会报错
5.dict.get():如果没有参数 key 直接返回 None
5.key in dict:返回布尔值,python2.7 中是 dict.has_key("key") 。python3 中已删除
6.setdefault():为字典添加新值,但如果添加的这个 key 原本存在则不添加
7.dict1.update(dict2):把 dict2 添加到 dict1 ,如果重复则更新,不重复则添加
8.dict.items():dict 转 tuple (看结果只转了第一层)
# Author:Liu
info = {
"aaa": "111",
"bbb": "222",
"ccc": "333",
"ddd": {
"ddd-1": 1,
"ddd-2": 2,
"ddd-3": 3
}
}
print(info.items())
# 输出:dict_items([('aaa', '111'), ('bbb', '222'), ('ccc', '333'), ('ddd', {'ddd-1': 1, 'ddd-2': 2, 'ddd-3': 3})])
9.fromkeys():初始化一个 dict
test = dict.fromkeys([6, 7,"link"], {"key": "value"})
test["link"]["key"] = "new_value"
print(test)
# 输出 {6: {'key': 'new_value'}, 7: {'key': 'new_value'}, 'link': {'key': 'new_value'}}
# 注:有引用问题
pass
- 占位符,暂时什么也不写,避免报错
集合及其方法
- 一种数据类型
- 没有重复
- 无序
# Author:Freeman
list_1 = [1, 4, 5, 7, 3, 6, 7, 9]
list_1 = set(list_1)
print(set(list_1), type(list_1))
# 输出:{1, 3, 4, 5, 6, 7, 9} <class 'set'>
- set() :转换为集合
- intersection():取交集
- union():取并集
- difference():差集
- issubset():判断是否是子集
- isuperset():判断是否为父集
- symmetric_difference():A与B 的交集C,(A - C)并(B - C)
- isdisjoint():是否有交集
- & | - ^:交 并 差 对称差
- add():添加一项 set.add(42)
- update():添加多项 set.update([1,5,3,6])
- remove():
- len(s):长度
- in / not in :判断是否在其中
- pop():删除并返回删除的东西
- discard():删除,不返回任何东西
文件操作
- open() 打开文件
- read() 读文件
- encoding="utf-8" 用 utf-8 编码格式打开(否则会报错或乱码),国内 windows 默认为 GBK 编码
data = open("yesterday",encoding="utf-8").read()
print(data)
- 文件对象
f = open(xxx,encoding="utf-8") # 文件句柄,这里指向文件的内存地址
# Author:Freeman
f = open("yesterday","r", encoding="utf-8") # r 读 w 写,不写为默认 r
data = f.read()
print(data) # print(f.read()) 不报错但也不出结果
- 文件的模式
1.w 为重新创建(原来的就没了),重新创建了一个名为 xxx 的文件
2.r 为只读
3.a(append)追加 在源文件的后面追加
4.r+ 既能读又能写,但写是在最后面添加
5.w+ 写读模式
6.a+ 追加读写
7.rb 二进制格式读文件 (Python3.0里网络传输只能用二进制格式)
8.wb 二进制格式写文件
9.ab 二进制格式追加文件 - readline() 读文件的一行,加参数为第几列
- readlines() 将文件转换为一个 list ,源文件的每一行为 list 中的一个元素
- write():
1.每次只写 \n 会被合并为一个
2.如果写完之后,通过 seek() 重新定位,下次写的时候会覆盖而不是把之前的内容向后推 - 读文件的最优方式:只占一份内存
for line in f:
print(line.strip())
- tell():返回文件中的 光标 位置 1 个数字或英文字母占一个;全角数字、汉字占三个
- seek():重新设置 光标 位置。并不是所有类型的文件都可以移动光标,因此有了 seekable() 方法
- encoding():打印编码
- flush():比如 txt 文件,通常是存储在硬盘上,但为了保证速度,许多时候都是在缓存中进行操作,flush() 方法是强制刷新,比如涉及钱时必须保证写了多少立刻存起来,防止突然断电
- 一个进度效果
# Author:Freeman
import sys, time
for i in range(10):
sys.stdout.write("#")
sys.stdout.flush()
time.sleep(.5)
- truncate():无视 seek() 定位的光标,当 open 的文件为 a 时,从文件开始截取制定数量的字符,不写参数默认全部截取