异常是程序运行时发生错误的信号

我们可以使用异常处理机制来捕捉异常,当捕捉成功后,将进入另外的一个处理分支,执行预定的逻辑

try:
    a = input('please input a number')
    int(a)
except:
    print('你输入的不是数字!')
finally:
    print('程序结束')#不管对不对,都会执行

也可以打印特定错误

s1 = 'hello' 
try:
    int(s1) 
except ValueError as e: 
    print(e)
print('输入错误')#用捕获机制这行也会运行
#Exception万能异常种类

主动报错

try:
    raise TypeError('类型错误') 
except Exception as e: 
    print(e)

断言

assert 1 == 1 
assert 1 == 2

json

序列化
将原本的字典、列表等内容转化为一个字符串的过程叫做序列化

序列化的目的:

  1. 以某种存储形式使自定义对象持久化
  2. 将对象从一个地方传递到另外一个地方
  3. 使程序更具有维护性
    json模块提供四个功能:dumps\dump\loads\load

dumps:从变量里将字典类型的数据转换为str

loads:将str转换为dict

dump:将字典转换为str并写道json文件里面

load:从json中读取数据

import json
dict = {'e1':4,'da':6,'cds':75}
str_dict = json.dumps(dict)#序列化,将一个字典转化为字符串
print(type(dict),dict)
print(type(str_dict),str_dict)

dic = json.loads(str_dict)
print(type(dic),dic)#反序列化

dict1 = {'你好':1,'谢谢':2,'小笼包':3,'再见':4}

json_dict1 = json.dumps(dict1,sort_keys=True,indent=2,separators= (',',':'),ensure_ascii=True)
print(json_dict1)#ensure_ascii如果不关掉,中文都会以\uxxxx显示
json_dict = json.dumps(dict1,ensure_ascii=False)
print(json_dict)

with open('test.txt','w',encoding='utf-8') as f:
    json.dump(dict1,f,ensure_ascii=False)#写入文件

# <class 'dict'> {'e1': 4, 'da': 6, 'cds': 75}
# <class 'str'> {"e1": 4, "da": 6, "cds": 75}
# <class 'dict'> {'e1': 4, 'da': 6, 'cds': 75}
# {"\u4f60\u597d": 1, "\u8c22\u8c22": 2, "\u5c0f\u7b3c\u5305": 3, "\u518d\u89c1": 4}
# {"你好": 1, "谢谢": 2, "小笼包": 3, "再见": 4}

# test.txt
# {
#   "\u4f60\u597d":1,
#   "\u518d\u89c1":4,
#   "\u5c0f\u7b3c\u5305":3,
#   "\u8c22\u8c22":2
# }
Skipkeys
1,默认值是False,如果dict的keys内的数据不是python的基本类型,2,设置为False时,就会报 TypeError的错误。此时设置成True,则会跳过这类key,3,当它为True的时候,所有非ASCII 码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的 中文即可正常显示。
indent 是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行 且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json 
ensure_ascii 当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设 置为False即可,此时存入json的中文即可正常显示。 
separators 分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示 dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 
sort_keys 将数据根据keys的值进行排序

hashlib

hashlib提供了常见的摘要算法,如MD5,SHA1

import hashlib

md5 = hashlib.md5()#sha1调用方式相同
md5.update('hello world'.encode('utf-8'))
print(md5.hexdigest())

configparser

用于生成与windows.ini风格类似的配置文件,包含一个或多个节,每个节包含多个键值对

import configparser
conf = configparser.ConfigParser()

conf['DEFAULT'] = {'ServerAliveInterval':'45',
                   'Compression':'yes',
                   'CompressionLevel':'9',
                   'ForwardX11':'yes' }
conf['xxx.org'] = {'User':'hg'}
conf['shangxizhuan.site'] = {'Port':'50022',
                                'ForwardX11':'no' }
with open('config','w') as config:
    conf.write(config)
#查找并打印
print(conf['shangxizhuan.site']['Port'])
for key in conf['xxx.org']:
    print(key)

增删改查

import configparser
conf = configparser.ConfigParser()

conf.read('config')

conf.add_section('local')#添加键

conf.remove_section('xxx.org')#删除节

conf.remove_option('shangxizhuan.site','Port')#移除条目

conf.set('shangxizhuan.site','port','11111')#再对于键吓加上条目

conf.write(open('config.new','w'))#写入文件

logging

logging模块默认状态吓将日志打印到标准输出中,切只显示大于WARNING的日志(日志级别等级CRITICAL > ERROR > WARNING > INFO >DEBUG),默认格式为日志级别:Logger名称:用户输出的消息

logging库提供了多个组件:logger\handler\formatter,logger对象提供课直接使用的接口,handler发送日志到合适的目的地,filter提供过滤日志信息的方法,formatter指定日志显示格式。logger.setLevel()\fh.setLevel()都可以对文件流进行级别设置

import logging

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    # filename='test.log',
                    # filemode='w')
                    )
logger = logging.getLogger(__name__)#初始化,name可以不填

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

'''
logging.basicConfig()函数通过具体参数更改logging模块默认行为,参数具体为:
filename\filemode:创建日志文件,指定文件打开方式,如果不写则日志信息会被输出到控制台
format:指定handler使用的日志现实格式
datefmt:指定日期时间格式
level:设置从哪一级别开始报

format的参数:
参数:作用
 
%(levelno)s:打印日志级别的数值
%(levelname)s:打印日志级别的名称
%(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s:打印当前执行程序名
%(funcName)s:打印日志的当前函数
%(lineno)d:打印日志的当前行号
%(asctime)s:打印日志的时间
%(thread)d:打印线程ID
%(threadName)s:打印线程名称
%(process)d:打印进程ID
%(message)s:打印日志信息
'''

对文件操作


import logging

logger = logging.getLogger()#创建一个handler,用于写入日志文件
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("log.txt")#用于写入文件

ch = logging.StreamHandler()#用于输出到控制台
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(handler)# looger对象可以添加多个handler对象
logger.addHandler(ch)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

logging的配置文件

import os
import logging.config
import datetime
import time

# 定义三种日志输出格式 开始

standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'  # 其中name为getlogger指定的名字

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'

# 定义日志输出格式 结束

logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录

date_time = str(datetime.date.fromtimestamp(time.time()))

logfile_name = 'access' + date_time + '.log'  # log文件名

# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)

# log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
    },
    'filters': {},
    'handlers': {
        # 打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'DEBUG',
            # 'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            "class": "logging.handlers.TimedRotatingFileHandler",  # 依照时间进行切割
            'formatter': 'standard',
            'filename': logfile_path,  # 日志文件
            # 'maxBytes': 1024*1024*5,  # 日志大小 5M
            "when": "h",  # 小时格式
            "interval": 24,  # 24 小时
            'backupCount': 7,  # 7个
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    'loggers': {
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
        },
    },
}


def load_my_logging_cfg():
    logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    logger = logging.getLogger(__name__)
    logger.info('hello!')


if __name__ == '__main__':
    load_my_logging_cfg()

# 我们只需把配置写道字典中就行
# 1.从字典中加载配置logging.config.dictConfig(LOGGING_DIC)
# 2.logger对象来产生日志,logger对象都是配置到字典的loggers键对应的子字典

time

time.sleep(sec):线程推迟一定时间后再运行,单位为秒

time.time():获取当前时间戳

python中一般有三种表示时间的方式:时间戳、元组、格式化的时间字符串

  1. 时间戳:从1970年1月1日00:00:00到现在偏移的秒数,float,time.time()
  2. 元组(结构化时间):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等),time.localtime()
  3. 格式化的时间字符串(Format String)‘1999-12-06’,time.strftime()

格式化表示法

%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身

三种时间的转换关系:
avatar

import time
print(time.time())#时间戳
print(time.localtime())#结构化时间,元组
print(time.strftime('%Y-%m-%d %H-%M-%S'))#格式化时间

#时间戳————》结构化
t12 = time.localtime(t1)
print(t12)

#结构化————》时间戳
t21 = time.mktime(t2)
print(t21)

#结构化————》格式化
t23 = time.strftime('%Y-%m-%d %H-%M-%S',t2)
print(t23)

#格式化————》结构化
t32 = time.strptime(t3,'%Y-%m-%d %H-%M-%S')
print(t32)

计算时间差

start_time=time.mktime(time.strptime('2017-09-11 08:30:00','%Y-%m-%d %H:%M:%S'))
end_time=time.mktime(time.strptime('2019-09-12 11:00:50','%Y-%m-%d %H:%M:%S'))
dif_time=end_time-start_time 
struct_time=time.gmtime(dif_time)
print('过去了%d年%d月%d天%d小时%d分钟%d秒'%(struct_time.tm_year- 1970,struct_time.tm_mon-1, struct_time.tm_mday- 1,struct_time.tm_hour, struct_time.tm_min,struct_time.tm_sec))

os

OS模块是与操作系统交互的一个接口

路径

os.chdir("dirname"):改变当前脚本工作目录,等于cd
os.curdir()返回当前目录
os.pardir()获取当前目录的父目录字符串名

文件夹

os.mkdir('dirname')生成单机目录
os.rmdir('dirname')删除单级空目录
os.removedirs('dirname')向上递归删除空目录
os.remove()删除文件
os.rename('old','new')重命名
os.stat('path/file')获取文件目录信息

操作系统差异

os.system("bash command") 运行shell命令,直接显示
os.popen("bash command).read() 运行shell命令,获取执行结果
os.environ 获取系统环境变量

路径相关

os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空
值,即os.path.split(path)的第二个元素。
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[,
path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小

re

正则表达式模块
re.findall('a[abc]b', 'aab abb acb adb afb a_b')

\w 匹配字母(包含中文)或数字或下划线
\W 匹配非字母(包含中文)或数字或下划线
\s 匹配任意的空白符
\S 匹配任意非空白符
\d 匹配数字
\D 匹配非数字
\A 从字符串开头匹配
\z 匹配字符串的结束,如果是换行,只匹配到换行前的结果
\n 匹配一个换行符
\t 匹配一个制表符
^ 匹配字符串的开始
$ 匹配字符串的结尾
.
匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任
意字符。
[...] 匹配字符组中的字符
[^...] 匹配除了字符组中的字符的所有字符
* 匹配0个或者多个左边的字符。
+ 匹配一个或者多个左边的字符。
? 匹配0个或者1个左边的字符,非贪婪方式。
{n} 精准匹配n个前面的表达式。
{n,m} 匹配n到m次由前面的正则表达式定义的片段,贪婪方式
a b
() 匹配括号内的表达式,也表示一个组

shutil

文件、文件夹、压缩包处理模块

文件相关

import shutil
#把文件内容拷贝到另外一个文件中
shutil.copyfileobj(open('db.txt','r'),open('log.txt','w'))

#拷贝文件,目标文件无需存在
shutil.copyfile('db.txt','db.txt.bat')

#仅拷贝权限,内容、用户、组都不变,m目标文件必须存在
# shutil.copymode('a','b')

#仅拷贝状态信息,目标文件必须存在
# shutil.copystat('a','b')

#拷贝文件和权限,目标文件必须存在
# shutil.copy('a','b')

#递归拷贝文件夹
# shutil.copytree(src, dst, symlinks=False,ignore=None)

#递归删除
# shutil.rmtree('xx')

#递归移动,可用于重命名
# shutil.move('xx1','xx2')

压缩包相关

ret = shutil.make_archive('db.txt','zip',root_dir='./')
压缩包名,压缩种类,目的路径,用户,组,日志

shutil使用zipfile和tarfile两个模块来处理压缩包

zipfile


import zipfile 
# 压缩 
z = zipfile.ZipFile('laxi.zip', 'w') 
z.write('a.log') 
z.write('data.data') 
z.close() 
# 解压 
z = zipfile.ZipFile('laxi.zip', 'r') 
z.extractall(path='.') 
z.close()

tarfile

import tarfile 
# 压缩文件 
t = tarfile.open('/tmp/egon.tar','w') 
t.add('/test1/a.py',arcname='a.bak') 
t.add('/test1/b.py',arcname='b.bak') 
t.close() 
# 解压缩文件 
t = tarfile.open('/tmp/egon.tar','r') 
t.extractall('/egon') 
t.close()

附加

jieba

分词用

pyinstaller

用于打包程序,在cmd里面使用
pyinstaller -F -i 图标.ico 代码.py

匿名函数

函数名 : lambda 参数 : 返回值

calc = lambda x,y : x*y
print(calc(2,6))

dic = {'k1':20,'k2':120,'k3':50}
print(dic[max(dic,key=lambda k :dic[k])])

常用内置函数

eval:执行字符串类型的代码,并返回最终结果

con = eval('print("hello")')       

exec:执行字符串类型的代码,但无返回

map():接收函数和list,并把每个元素依次作用在函数上,得到一个新的list并返回

list = map(lambda x : x*x,[i for i in range(1,11)])
for i in list:
    print(i)

globals():以字典格式返回全局变量

iter():生成迭代器

next():返回迭代器的下一个项目

len():返回对象长度或者元素个数

open():用于打开文件,创建一个file对象

print():打印输出

input():接收一个标准输入,返回为str

range():用于创建一个整数列表

dir():返回参数的属性、方法列表

dict():将元组、列表转化为字典

chr():ascii转字符

list():元组转字符

abs():返回绝对值

slice():实现切片对象

# 语法:
# class slice(stop)
# class slice(start, stop[, step])

s5 = slice(5)    
arr = [i for i in
print(arr)       
print(arr[s5])   

# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# [0, 1, 2, 3, 4]

sorted():将可迭代的对象进行排序(默认升序)操作

zip:将可迭代的对象中的元素打包成一个个元组

s5 = slice(5)                         
arr = [chr(i) for i in range(97,123)] 
no = [i for i in range(1,len(arr)+1)] 
print(arr)                            
print(no)                             
list = list(zip(arr,no))              
print(list)  

# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
# [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7), ('h', 8), ('i', 9), ('j', 10), ('k', 11), ('l', 12), ('m', 13), ('n', 14), ('o', 15), ('p', 16), ('q', 17), ('r', 18), ('s', 19), ('t', 20), ('u', 21), ('v', 22), ('w', 23), ('x', 24), ('y', 25), ('z', 26)]

__import__():用于动态加载类和函数

filter:过滤

def fun(x): return x%2==0
list = filter(fun,[i for i in range(10)])
print(list)
for i in list:
    print(i)

# <filter object at 0x000001F55B3C56A0>
# 0
# 2
# 4
# 6
# 8

max/min:返回最大/最小值。对字典默认按照key

迭代

我们用for循环把元素从容器里面取出来的过程叫做迭代

迭代是访问集合的一种方式,迭代器是一个可以记住遍历的位置的对象,迭代器对象从集合的第一个元素开始访问,知道所有元素被访问完结束,迭代器只能前进不能后退

list\tuple\str\dict\set等元素类型可以使用for...in...来取出里面的元素,这些称为可迭代对象。所有能够通过迭代来取出元素的都是可迭代对象

可以使用isinstance来判断是否可迭代

from collections import  Iterable
l = [1,2,3,4]

print(isinstance(l,Iterable))

可迭代对象内部都有__iter__方法

l = [1,2,3,4]

print(dir(l))

迭代器必须有iter和next方法

l = [1,2,3,4]
l_iter = l.__iter__()
print(dir(l_iter))
item = l_iter.__next__()
print(item)#输出1

可以用Iterable来判断是否是迭代器

from collections import  Iterator
l = [1,2,3,4]
l_iter = l.__iter__()
print(isinstance(l_iter,Iterator))

迭代是访问集合的一种方式,迭代器是一个可以记住遍历的位置的对象,迭代器对象从集合的第一个元素开始访问,知道所有元素被访问完结束,迭代器只能前进不能后退

list\tuple\str\dict\set等元素类型可以使用for...in...来取出里面的元素,这些称为可迭代对象。所有能够通过迭代来取出元素的都是可迭代对象

可以使用isinstance来判断是否可迭代

from collections import  Iterable
l = [1,2,3,4]

print(isinstance(l,Iterable))

可迭代对象内部都有__iter__方法

l = [1,2,3,4]

print(dir(l))

迭代器必须有iter和next方法

l = [1,2,3,4]
l_iter = l.__iter__()
print(dir(l_iter))
item = l_iter.__next__()
print(item)#输出1

可以用Iterable来判断是否是迭代器

from collections import  Iterator
l = [1,2,3,4]
l_iter = l.__iter__()
print(isinstance(l_iter,Iterator))

生成器

我们有时候想要获取函数的一些处理结果,但是如果用return,那么函数就结束了,如果用print,则可用性会变差,这里我们可以使用yield,生成器

def generator():
    a = 1
    print('给a赋值')
    yield a #k1
    b = 2
    print('给b赋值')
    yield b
g = generator() #生成器,不执行内部代码
print(g,next(g)) #触发运行,跑到k1停住
print(next(g)) #执行到b

# 给a赋值
# <generator object generator at 0x0000023AEB9F4BA0> 1
# 给b赋值
# 2
def generator():
    a = '米饭'
    for i in range(1000000):
        a = yield f'吃了第{i}个{a}陷的包子'#先执行yield返回,然后再执行a的赋值语句


pro = generator()
print(pro.__next__())
print(pro.send('三鲜肉'))#send=赋值+next
print(pro.send('粉丝'))
print(pro.send('咖喱牛肉'))
print(pro.send('雪菜'))
print(pro.send('牛肉'))

# 吃了第0个米饭陷的包子
# 吃了第1个三鲜肉陷的包子
# 吃了第2个粉丝陷的包子
# 吃了第3个咖喱牛肉陷的包子
# 吃了第4个雪菜陷的包子
# 吃了第5个牛肉陷的包子

# Process finished with exit code 0

列表推导式

a = [i for i in range(100)]

print(sum([i for i in range(1,101)]))

num = [i*i for i in range(100) if i % 3 is 0]

name = [['zhangsan','lisi','lixiuli','wangwu'],['tokugawa','ono','yochida','lilisu']]
print([namel for lst in name for namel in lst if 'li' in namel])#先取列表再取元素

name = ['zhangsan','lisi','lixiuli','wangwu','yochida']
print([namel for namel in name if 'li' in namel])

print('\n'.join('\t'.join([f'{i} x {j} = {i * j}' for i in range(1,j+1)])for j in range(1,10)))#99乘法表

把字母转小写并合并值

dic1 = {'a':1,'b':2,'y':1, 'A':4,'Y':9}
dict2 = {k.lower():dic1.get(k.lower(),0)+dic1.get(k.upper(),0) for k in dic1}
print(dict2)

字典推导式

k1 = {'a':1,'b':2,'c':3}
k2 = {k1[k]:k for k in k1}
print(k2)

格式化输出

a = int(input("a = "))
b = float(input("b = "))
print('%d %% %f = %.1f' % (a,b,a/b))

%d 表示整形,%f表示浮点数,%.1f表示保留一位小数,%%表示%,%s表示字符串

3.6以后可以以这种方式进行输出

a, b = 5, 10
print(f'{a} * {b} = {a * b}')

真值判断

a = int(input("a = "))
is_public = a % 6 ==0 and a % 3 ==0
print(is_public)

if

a = input("a = ")
if a =='pass' or a == 'stu':
    print('hello')
else:
    print('no')

循环

for

a = int(input("a = "))
sum = 0
for x in range(a):  #注意此处range是左闭右开
    sum += x
print(sum)

while

import random
a = random.randint(0,10) #此处为闭区间

while True:
    b = int(input("please input a number"))
    if b > a :
        print("大")

    elif b < a:
        print("小")

    elif b == a:
        print("对了!")
        break

函数

def panduan(num):   #判断奇偶
    if type(num) == int:
        if num % 2 ==0:
            print("是偶数")
        elif num % 2 ==1:
            print("是奇数")
    else:
        print("输的啥玩意")


if __name__ == "__main__":
    a = int(input("input a number"))
    panduan(a)

数组例子

def panduan(num):   #判断奇偶,这里可以进行数组
    for x in range(len(num)):
        if type(num[x]) == int:
            if num[x] % 2 ==0:
                print('%d 是偶数'%(num[x]))
            elif num[x] % 2 ==1:
                print("%d 是奇数"%(num[x]))
        else:
            print("输的啥玩意")


if __name__ == "__main__":
    a = input("input a number")
    num = [int(n) for n in a.split()]
    panduan(num)

数量可变参数

def panduan(num):   #判断奇偶
    for x in range(len(num)):
        if type(num[x]) == int:
            if num[x] % 2 ==0:
                print('%d 是偶数'%(num[x]))
            elif num[x] % 2 ==1:
                print("%d 是奇数"%(num[x]))
        else:
            print("输的啥玩意")


if __name__ == "__main__":
    a = input("input a number")
    num = [int(n) for n in a.split()]
    panduan(num)

此处结果为
2
(3, 4, 5)

动态传参,可以传入任意多个参数,作为元组

def max_num(*args):
    max_one = 0
    for i in args:
        if i > max_one:
            max_one = i
    return max_one

两个星号传入的是键值对

def max_num(**args):
    print(args)

max_num(site='osaka',num=1234567)

python 闭包

from urllib.request import urlopen

def func():
    content = urlopen('http://myvip.ipip.net')
    def get_content():
        return content
    return get_content

code = func() #此处code传入的是get_content函数的地址
content = code() #此处等于执行get_content()
print(content.decode('utf-8'))

#这样在content获取了一次地址后,以后只需调用第一次的地址,不用再打开网页重新获取了

修饰器

def decorator(func):
    def wrapper(*args, **kwargs):
        print('123')
        return func(*args, **kwargs)

    return wrapper

def say_hello():
    print('同学你好')

say_hello_super = decorator(say_hello)
say_hello_super()


#等同于

def decorator(func):
    def wrapper(*args, **kwargs):
        print('123')
        return func(*args, **kwargs)

    return wrapper

@decorator
def say_hello(): #say_hell0 = decorator(say_hello)
    print('同学你好')

say_hello()

模块与调用

以上面的panduan(num)这个函数为例,现在我们把他放在test1.py里面,如果我们想要使用这个函数,我们可以import test1

但是,如果出现同名函数,后面的那个会覆盖掉前面的,如上面panduan函数第一个是直接判断数字,第二个是能够处理数组的,如果在main里面同时写这两个函数,主程序调用时效果会是调用数组的那个。此时我们假设把直接判断的放进test1.py,把判断数组的放进test2.py,然后我们想要调用哪个就improt哪个头文件,如from test2 import panduan,或者

import test1 as t1
import test2 as t2

t1.panduan(num1)
t2.panduan(num2)

class Test:
    # __init__是一个特殊方法用于在创建对象时进行初始化操作
    # 如果你想要把属性的权限设为私有,只需要在他们前面加双下划线
    def __init__(self, foo):
        self.__foo = foo

    def __bar(self):
        print(self.__foo)
        print('__bar')

    # 我们也可以在属性前面加单下划线,表示其是受保护的

class Person(object):

    # 限定Person对象只能绑定_name, _age和_gender属性
    __slots__ = ('_name', '_age', '_gender')

    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

    #@property是装饰器,可以用来修饰只读属性

    #@property用在方法上,可以把方法变成属性

class DataSet(object):
  @property
  def method_with_property(self): ##含有@property
      return 15
  def method_without_property(self): ##不含@property
      return 15

l = DataSet()
print(l.method_with_property) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
print(l.method_without_property())  #没有加@property , 必须使用正常的调用方法的形式,即在后面加()

# 或者@property可与属性结合,隐藏属性名来达到安全的效果

class DataSet(object):
    def __init__(self):
        self._images = 1
        self._labels = 2 #定义属性的名称
    @property
    def images(self): #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户有没办法随意修改。
        return self._images 
    @property
    def labels(self):
        return self._labels
l = DataSet()
#用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。
print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。

静态方法

from math import sqrt


class Triangle(object):

    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

    @staticmethod
    def is_valid(a, b, c):
        return a + b > c and b + c > a and a + c > b

def main():
    a, b, c = 3, 4, 5
    # 静态方法和类方法都是通过给类发消息来调用的
    if Triangle.is_valid(a, b, c):
        t = Triangle(a, b, c)
        print(t.perimeter())
        # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
        # print(Triangle.perimeter(t))
        print(t.area())
        # print(Triangle.area(t))
    else:
        print('无法构成三角形.')


if __name__ == '__main__':
    main()

继承

class model(object):
    def __init__(a,b):

.......


class mod2(model):

    def __init__(a,b,c):
        super().__init__(a,b)
        self.c = c

文件读写

操作模式具体含义
'r'读取 (默认)
'w'写入(会先截断之前的内容)
'x'写入,如果文件已经存在会产生异常
'a'追加,将内容写入到已有文件的末尾
'b'二进制模式
't'文本模式(默认)
'+'更新(既可以读又可以写)
f = open('./xx.txt', 'r', encoding='utf-8')
print(f.read())
f.close()


#用try来报错示例
try:
    fh = open("testfile", "w")
    fh.write("这是一个测试文件,用于测试异常!!")
except IOError:
    print "Error: 没有找到文件或读取文件失败"
else:
    print "内容写入文件成功"
    fh.close()


#逐行读取
for line in open("foo.txt"):
    print line, #,会忽略换行符


#快速方法,结束时会自动关闭文件
with open(xxxx) as f:
    print(f.read())