服务器
1.ftp服务器
FTP是FileTransferProtocol(文件传输协议)的英文简称,中文名称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序。基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议以传输文件。
在FTP的使用当中,常遇到两个概念:“上传”“下载”。
2.samba服务器
Samba是在linux和UNIX系统上实现一个免费软件,能够完成在windows,mac操作系统下访问linux系统下的共享文件。
3.ssh服务器
SSH为建立在应用层和传输层基础上的安全协议。是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议,常用于远程登录,以及用户之间进行资料拷贝。可有效防止远程管理过程中的信息泄漏问题。
python2与3的区别
1.在python2版本中,一般在代码中不能识别中文字符,但必须 在开头处顶格写上#coding=utf-8(编码),不过python推荐#-*-coding:utf-8 -*-
2.在python2中,对象输入时为raw_input()函数,而python3只有input()函数
3.python2里面,input时输入3+4会自动转为公式执行,而python3则返回一个字符串"3+4",如果python2要改成字符串输出就要用raw_input
3.关键字 if/else/for/break/inport/class/def/None/not/in/from/return/elif/continue/while/and/or/True/False/try/except/finally/as/global/lambda,pass,raise,del
python的语法
1. print:print(“age变量里的值是%d”%age) (print(“%d”%i)#print(i)
print(“name变量里的值是%s”%name)
print(“Love”*5) (可以重复字符串)
print(“姓名是:%xx,年龄是:%xx”%(name,age)) (同时打印多个变量)
print(“*”,end “ ”) (print打印之后不换行)
print(“ ”) (打印之后换行)
在print语句中,字符串后面会默认接一个\n符号,即换行,但是如果要在一个字符串后面跟着逗号,换行就被取消,例如:
for i in [1,2,3,4,5]
print i #打印一个即换行
print i, #打印一个不换行
2.\t:表示一个tab键,它不会换行
3.驼峰命名法(目的:增强目的的可读性)
englishScore= 100 (小驼峰法)EnglishScore= 100(大驼峰法)
english_score= 100(推荐)
4.比较运算符
==,!=,<>(不等于),>,<,>=,<=
5.算数运算符
+,-,*,/,//(取整),%(取余),**(幂运算)
6.逻辑运算符
and,or,not
7.程序的3大执行流程
- 顺序执行
- 选择执行
- 循环执行
8.if-else(判断两件)
if条件:条件满足的语句
else:
条件不满足的语句
9.if-elif(判断多件)
if条件1:条件满足的语句
elif条件2:
条件满足的语句
elif条件3:
条件满足的语句
10.while 循环
while 条件:条件满足的时候执行的事情
11.for 循环
for 变量名 in name:
12.break,continue和return
break的含义是要在这个地方中断循环,并跳出循环体continue是从当前位置跳到最后一行的后面,不执行最后一行,对一个循环体而言,如同首尾衔接一样
return在函数中,使用单个的return,并不是返回一个值,而是结束正在执行的函数,有点类似循环中的break作用
13.交换两个变量的方式
第一种:需要第三个变量a=3
b=4
c=0
a=b
b=c
第二种:不需要第三个变量
a=3b=4
a=a+b
b=a-b
a=a-b
第三种:不需要第三个变量
a,b= b,a
14.查看对象的内存的地址:id(对象)
15.查看对象的类型:type(对象),对象有类型,变量无类型
16.整数溢出问题
在某些编程语言中,整数溢出是必须正视的,但是在python里面就无需忧愁,原因就是它支持“无限精度”的整数,即不用考虑整数溢出的问题,int类型与任意精度的long整数类可以无缝转换,超过int范围的情况都将转换成long类型
17.内建函数
- divmod(5,2) #返回商和余数
- round(1.12345,2) #第二个数表示四舍五入小数位数
- abs(-10) #求绝对值
18.常用数学函数(乘方,开方,对数运算,需导入math模块)
- dir(math)能显示math模块的所有内置函数
- help(math.pow)能显示该内建函数的用法
- dir()和help()对学习模块很重要
19.格式
#!/usr/bin/env python #引导程序找到python解析器#_*_ coding:utf-8 _*_ #编码格式utf-8
20.cmp(str1,str2)比较
- 返回的数值小于0,说明第一个str1小于str2
- 返回的数值等于0,说明第一个str1等于str2
- 返回的数值大于0,说明第一个str1大于str2
ord():将单个字符转换为ASCII,ord('a') = 97
chr():将ASCII转换为单个字符,chr(97) = 'a'
21.三元操作符
A = Y if x else Z
如果x为真,那么执行A=Y
如果x为假,那么执行A=Z
字符串
1.cpu,内存,硬盘
cpu读写快,但存储小。而硬盘读写慢,但存储大。所以诞生了内存这一概念位于二者之间
2.数字和字符串的存储
如果是一个数字可以用一个字节存储,如果是字符串则不管双引号内是什么都要单独占一个字节
3.组成字符串的2种方式
第一种:A= “lao” B=“wang” C=A+B第二种:C=“===%s===”%(A+B)
4.字符串中的下标
name=“abcdef” name[0]=“a” name[-1]=“f” name[6]=xxx(越界导致异常)
6.字符串切片和逆序
切片:name=“abcdef” name[2:5]=“cde”跳取:name=“abcdef” name[2:-1:2]=“ce”
逆序:name=“abcdef” name[-1::-1]=“fedcba”
7.字符串的常见操作
myStr= “hello world itcast and itcastxxxcpp”
输入:myStr.find(“world”) 输出:6(6表示从左边算起w的下标)
输入:myStr.find(“feige”) 输出:-1(-1表示没有该字符串)
输入:myStr.rfind(“itcast”) 输出:23(23表示从右边开始查找,但是下标仍是 左边开始计算)
输入:myStr.index(“feige”) 输出:程序异常(index与find相似,区别只是当搜 索字符串不存在时,index会异 常,而find会输出-1)
输入:myStr.count(“itcast”) 输出:2(2表示count计数到itcast有两次)
输入:myStr.count(“feige”) 输出:0(要是发现不到该字符串就输出计数为0)
输入:myStr.replace(“world”,“World”) 输出:“helloWorld itcast and itcast...”(此处只会改变输出结果,但不会对原字符串myStr改变)
输入:myStr.replace(“itcast”,“xxx”,1)输出:“helloworld xxx and itcastxxxcpp”(1表示替换一个itcast,如果没有1则表示itcast全部替换xxx)
输入:myStr.split(“”) 输出:[“hello”,“world”,“itcast”,“and”,“itcastxxxcpp”](字符串分隔切片)
输入:myStr.split(“”,2) 输出:[“hello”,“world”,“itcastand itcastxxxcpp”]
输入:myStr.capitalize() 输出:“Helloworld itcast and itcastxxxcpp”(把字符串的第一个字符大写)
输入:myStr.title() 输出:“HelloWorld Itcast And Itcastxxxcpp”(把字符串的每个单词首字母大写)
输入:myStr.center(50) 输出:“ helloworld itcast and itcastxxxcpp ”(返 回一个原字符串居中)
输入:myStr.partition(“itcast”) 输出:(“helloworld”,“itcast”,“anditcastxxxcpp”)(将字符串分隔成三部分,itcast前和itcast和itcast后)
输入:myStr.rpartition(“itcast”) 输出:(“helloworld itcast and ”,“itcast”,“xxxcpp”)(从右边开始算,将字符串分成三部分)
file_name =“xxx.txt”
输入:file_name.endswith= “.txt” 输出:True (判断后缀是不是obj结束)
name =“wang xxx”
输入:name.startswith= “wang” 输出:True (判断前缀是不是obj开头)
myStr =“HELLO world itcast and itcastcpp”
输入:myStr.lower() 输出:“helloworld itcast and itcastcpp”(转换字符串中所 有大写字符为小写)
输入:myStr.upper() 输出:“HELLOWORLD ITCAST AND ITCASTCPP”(转换字符串中所有小写字符为大写)
输入:myStr.strip()输出:“HELLOworlditcastanditcastcpp”(删除所有空格,lstrip删除左边所有空格,rstrip删除右边所有空格)
myStr =“hello”
输入:myStr.rjust(10) 输出:“ hello”(返回一个原字符串右对齐,ljust为 左对齐)
myStr =“hello\nworld”
输入:myStr.splitlines() 输出:[“hello”,“world”](返回一个包含各行作为元素的 列表)
myStr =“abc”
输入:myStr.isalpha() 输出:True(用于判断字符串是否为纯字母)
输入:myStr.isdigit() 输出:false(用于判断字符串是否为纯数字)
输入:myStr.isalnum() 输出:True(用于判断字符串是否为纯数字或纯字母)
输入:myStr.isspace() 输出:False(用于判断字符串是否为纯空格)
a =[“aaa”,“bbb”,“ccc”] b=“=”
输入:b.join(a) 输出:“aaa=bbb=ccc”(a中的每个字符用b来连接)
8.替换某些字符串为其他字符的解决思路:
答:我们知道字符串是不可变类型,是不能直接就改的,那么就先要将其转化为列表,然后在循环中找到该元素,通过列表进行更改
如:for i,string in enumerate(list):if string == "love":
list[i]="automn"
列表
1.定义一个列表
names= [“老王”,“老蒋”,“老李”](与c语言数组不同的是它可以存储不同的数据类型)
2.增删改查
增:names.append(“老赵”) names=[“老王”,“老蒋”,“老李”,“老赵”] (末尾)names.insert(0,“八戒”) names=[“八戒”,“老王”,“老蒋”,“老李”](插队)
names.extend(names1) 将names1的列表元素加到names中(合并)
append和extend:a.append(b)相当于把b作为一个整体扔到a
a.extend(b)相当于把b合并到a中
删:names.pop() 删除列表最后一个元素
names.remove(“老王”) 删除列表中的老王,且只能从左边开始删除一次
del names[0] 根据列表序号删除
坑!在删除元素的时候:num = [11,22,33,44,55,66]
for i in num:
if i == 33 or i == 44:
num.remove(i)
此时的结果是num = [11,22,44,55,66],即出现了漏删的情况,因为删完33时,44往前挪一位,即跳过了它,要想避免漏删就要在这个外面加上一个while True死循环
也可以把要删的全部组合成另一个列表b,然后一个for循环,for i in b: num.remove(b)
改:names[0]=“老刘”根据列表序号改动元素
查:if“老王”in names:
print(“找到了……”)
if “老王”not in names:print(“可以添加老王……”)
list.count("laowang") #统计出某个元素在该list中出现的次数
list.index("laowang") #返回元素的下标序号,如果没有就报错
list.insert(i,x) #传递两个参数,i表示序号,x表示参数
list.sort(cmp=None,key=None,reverse=False) #默认从大到小,key=len就是长度
同时得到元素索引和元素的解决思路:
seasons = ["spring","summer","automn","winter"]
list(enumerate(seasons))
3.while-for循环遍历列表
while:
whilei<5:
print(nums[i])
i+=1
可以使用len(nums)来测列表元素
for:(推荐)for temp in nums:
print(temp)
4.13.for-else(for循环里的东西全部遍历完之后,才会执行else里的代码)
for temp in nums:
print(temp)
else:
print(“========”)
5.sort的用法
list.sort(cmp = None,key = None,reverse = False)
reverse=True就是从大到小,key=len就是长度划分,reverse=True就是列表倒序
6.列表和字符串的相同点:索引,切片,合并
7.列表和字符串的不同点:在字符串中,每个元素只能是字符,在列表中,元素可以任意类型
8.列表和字符串最大的区别:列表可以改变,字符串不能改变
9.列表和字符串的转化:
line.split(" ")可以使字符串以空格方式隔开并以列表存放,".".join(name)列表可以用"."来连接列表的元素
10.列表与元组可以用list()和tuple()相互转化字典
1.定义一个字典
infor= {“name”:“班长”,“addr”:“山东”,“age”:“18”}print(“%s%s %d”%(infor[“name”],infor[“addr”],infor[“age”]))
2.增删改查
增:增加一个新的键值对
infor[“name”]= banzhang(只要键值不存在,赋予一个值就是增加)
d1.update(d2) :把字典2更新纳入字典1,但字典2依然存在
还可以d2.update(["(name","qiwsir")]),注意是两个小括号和一个大括号
删:删除一个键值对
del infor[“name”](重复删除会导致程序异常)
infor.pop("key"),删除指定键和整个键值对,没有则异常
infor.popitem(),不用参数,但一定随机删除一个键值对
改:修改一个键值对
只要这个键值存在,然后赋予新的值就是修改
查:查询一个键值对
infor[“name”](查询不存在的键值会导致程序异常)
推荐:infor .get(“name”)(存在则返回值,不存在时则无返回)
3.在列表中搜索字典
for temp in users:
if find_name == temp["name"]:
print("%s\t%d\t\t%s\t\t%d\t"%(temp["name"],temp["qq"],temp["weixin"],temp["number"]))
find_flag= 1
break
if find_flag == 0:
print("抱歉,没有找到您需要的名片…")
4.字典的遍历
infor= {“name”:“laowang”,“age”,“18”}
len(infor) = 2
infor.keys() [“age”,“name”]
if“qq” in infor.keys():
print(“有qq”)
infor.values() [18,“laowang”]
infor.items() (元组,既有key又有value)
for temp in infor.items:
print(“key= %s,value = %s”%(temp[0],temp[1]))
c,d= a = (11,22)
forA,B in infor.items():
print(“key= %s,value = %s”%(A,B))
5.将字典清空
infor.clear() 或者 infor = {} , 不过第二种并不是真正意义的清空,它只是指向了另一个对象
6.get和setdefault
infor.get("key")就是要得到某个键的值,也可以用infor["key"]来获取值但如果键不存在,就会异常,而infor.get()只返回一个空
infor.setdefault("key"),如果有这个键就会返回它的值,没有的话就创建这个键值对,而值变成None
7.items/iteritems,key/iterkeys,values/itervalues
infor.items()能够得到字典的列表,元素是键和值的元组
infor.iteritems()是一个"dictionary-itemiterator"类型,这种迭代器类型,必须用list转换一下,才能看到里面的真面目
元组
1.列表和元组基本没什么区别,都能存多个值,唯一的区别就是元组不让增删改(只读)
2.创建一个元组:
tup1= ('physics', 'chemistry', 1997, 2000)tup1= (50,)(如果是只有一个元素,可以添加逗号来消除歧义)
3.删除一个元组:
元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组del tup
4.修改一个元组:
元组中的元素值是不允许修改的,但我们可以对元组进行连接组合tup3= tup1 + tup2
5.访问一个元组:
元组可以使用下标索引来访问元组中的值print(tup1[0])
6.元组的内置函数
cmp(tuple1,tuple2):比较两个元组元素。
len(tuple):计算元组元素个数。
max(tuple):返回元组中元素最大值。
min(tuple):返回元组中元素最小值。
tuple(seq):将列表转换为元组
3.代码调试:可以在代码与代码中间加入print(“--------x--------”)来检测代码是否运行
集合
1.去重:可以用set()来去重复,也可以set = {},但并不推荐,因为容易与字典相混淆2.增删:
增:set.add("jack") #新添加元素
set.update("kim") #从另一个集合合并到一起
删:pop,remove,discard,clear
set.pop()不能有参数,且是随机删除,当删除到集合为空如果还要继续删除则发生异常
set.remove("obj") 删除指定的元素,没有则发生异常
set.discard("obj") obj是set里的元素就删除,不是就不做,不发生异常
set.clear()清空整个集合
3.元素和集合的关系
"obj" in set ,元素在集合内就返回True,没有就返回False
4. 集合与集合关系
相等与不等:a==b,a!=b ,正确就返回True,错误就返回False
子集:c<a ,True,c是a的子集
c.issubset(a)判断c是否是a的子集
并集:a.union(b) ,把a集合和b集合并起来
交集:a.intersection(b) ,把a集合和b集合交起来
5.名词
- 循环(loop),指的是在满足条件的情况下,重复执行同一段代码,比如while语句
- 迭代(iterable),指的是按照某种顺序逐个访问对象中的每一项,比如for语句
- 递归(recursion),指的是一个函数不断调用自身的行为,如以编程方式输出著名的菲波纳契数列(典型)
- 遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且每个节点只访问一项
函数
1.函数:把具有一个独立功能的代码块当作一个整体,这个整体就是函数2.目地:使程序变的更加模块化
3.函数的定义(代码封装):
def print_fozu():
print(“oo00oo”)
………..
4.注意:定义函数仅仅是定义,不能执行,需要调用
5.函数的调用
print_fozu()
6.带有参数的函数
defsum_2_nums(a,b):
………….
sum_2_nums(num1,num2)
7.函数的返回值
在不同函数之间,不能直接使用另一个函数里的变量,要用到return来返回这个变 量的值,再赋值给另一个变量
8.函数中的多个return
在函数中,只要执行到一个return,就返回结束,所以可以通过列表或元组来封装变 量的值
9.函数的四种类型
第一种:没有参数,没有返回值
第二种:有参数,没有返回值
第三种:没有参数,有返回值
第四种:有参数,有返回值
实参:当调用一个函数的时候,传递的值叫实参(实实在在传递的)
形参:用来接收的叫形参
10.函数的嵌套调用
def sum_3_nums(a, b, c):
result = a+b+c
#print("%d+%d+%d=%d"%(a,b,c,result))
return result
def average_3_nums(a1, a2, a3):
result = sum_3_nums(a1, a2, a3)
result = result/3 #result/=3
print("平均值是:%d"%result)
#1.获取3个数值
num1= int(input("第1个值:"))
num2= int(input("第2个值:"))
num3= int(input("第3个值:"))
#sum_3_nums(num1,num2, num3)
average_3_nums(num1,num2, num3)
11.局部变量:在一个函数里能用,出了这个函数哪都用不了,这样的变量称为局部变量
12.全局变量:定义在函数外面的变量,在整个代码中都可使用
13.如果一个变量已经在全局变量的位置定义了,此时还想在函数中对这个全局变量进行修改的话,仅用一个变量名=一个值还不够,它只是一个局部变量,只是和全局变量名字相同罢了,那么就需要在修改语句前加上global 变量名,这是对一个全局变量的声明,但是列表和字典可加可不加
14.只要在函数调用之前有这个全局变量,那么在调用函数的时候就可以使用这个全局变量
15.全局变量和局部变量名字相同,在函数里会使用局部变量,默认是定义
16.为了规避全局变量和局部变量名字相同,定义全局变量的时候g_a=100
17.函数帮助文档是help(test),在函数的开头处用一对双引号或者三对双引号来括起帮助
18.函数的缺省参数:调用函数时,缺省参数的值如果没有传入,则被认为是默认值,如print默认是换行,有了end就是就不换行
19.不定长参数:如sum_2_nums(a,b,*args)形参用来传递一个不定长的参数,args打印出来的格式为元 组,元组如果只有一个元素,必须在元素后面加上逗号,否则不是元组
如test(a,b,c=33,*args,**kwargs)形参,如果实参在传递的时候有变量名的赋值就是字 典的形式存储在kwargs中,没有变量名的就是args里
拆包:在传递参数的时候,如test(11,22,33,*A,**B)就可以将A的内容传递到元组,B的内容传递到字典
20.引用:id(变量名)获取变量名的地址
在python中不是变量存储了一个数值,而是这个字符指向了一个数据而已,它可以说是一个数据的地址,在A=B赋值语句中也就是把B存储的地址给了A一份,使得B也指向了这个数据
21.可变类型和不可变类型
- 数字(不可变)
- 字符串(不可变,因为所有的东西都是引用)
- 元组(不可变)
- 列表(可变)
- 字典 (可变)
22.递归
一个函数里边调用了函数本身,这样的函数叫递归(一定要想清楚什么时候结束调 用,否则会一直进行调用本身死循环,等内存使用完了之后就会死机,就像手机打开 app闪退)
def getNums(num):if num>1:
#此处注意要有返回值到下一个调用的函数中
return num*getNums(num-1)
else:
return num
result= getNums(4)
print(result)
23.函数中的文档
在函数开头处的第一行,用三个引号的方式包裹着对函数的说明print test.__doc__就是显示文档内容,其为内建函数
24.形参和实参
形参:形参表示一个值,过程希望调用时,传递该值实参:实参表示在调用过程中传递给过程形参的值,在调用代码过程中需提供参数
25.命名空间命名空间:表示标识符的可见范围,它是对作用域的特殊抽象,它包含处于该作用域的标识符
匿名函数
1.用lambda关键词能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤
2.lambda函数的语法只包含一个语句,如下:lambda[arg1[,arg2,arg3…]]:expression
lam = lambda x:x+3 ret = lam(3)
3.lambda函数能接收任何数量的参数但只能返回一个表达式的值
4.匿名函数的应用
def test(a,b,func)result= func(a,b)
return result
num= test(11,22,lambda x,y:x+y)
print(num)
4.列表里如果全是数字:
排序:nums.sort()(小到大)nums.sort(reverse=True)(大到小)
倒序:nums.reverse()
5.如果列表里是字典:
infors.sort(key=lambdax:x[‘name’])(按name的首字母来排序)
6.静态语言:先确定功能,再执行
动态语言:写完代码,运行的一霎那,功能才被确定
7.输入强制转换为公式:
如在转换输入类型的时候使用func_new= eval(func_new)就可转换成公式,即所有的 输入都将转换为输入,与int是一个道理文件操作
1.在linux系统中:一切设备皆文件
2.文件的打开与关闭
打开:f= open(“test.py”,“r”) (需要用f赋值)#r只能读(必须存在),w只能写(存在则覆盖,不存在就创建),a打开文件用于 追加(存在则追加,不存在就新建)
#rb以二进制格式打开一个文件只读,wb以二进制格式打开一个文件用于写入,ab以二进制格式打开文件追加内容
#r+打开一个文件用于读写,w+打开一个文件用于读写,a+打开一个文件用于读写
#rb+,wb+,ab+与上述类似,二进制文件可读可写
关闭:f.close()
3.文件的读和写
读:f.read(x) #x表示read读第几个,注意需要用一个变量接收,然后打印,程序才会出结果写:f.write(“haha”) #它会返回当前输入的个数
4.python的文件复制代码
# _*_ coding:utf-8 _*_f = open("19-交换变量的值.py","r")
content = f.read()
f.close()
f = open("xxx.txt.py","w")
f.write(content)
f.close()
5.得到例如jack[复件].txt的复制文件
read是读字符串,readline是读一行(字符串),readlines是全部读出的列
7.大文件的处理方法
读到大文件的时候切记不能用read为避免程序挂掉,所以在这时,不能一次性全部读取,需要加入一个循环,每次读 取1024个字节,等读取不到字节了,这时再break
whileTrue:
content = old_file.read(1024)
if len(content)==0:
break
new_file.write(content)
8.文件的定位读写
f.seek(2,0):seek可以理解为一个指针,第二个数字表示大方向,0是文件的开头,1是文件的当前未知,2表示文件末尾,类似于粗调,第二个数字是偏移量,类似于细调f.tell():获取当前的读写位置
9.文件,文件夹的相关操作
import os(引入os包)
修改文件名:os.rename(“xxx.py”,“x.py”)
删除文件:os.remove(“x.py”)
创建文件夹:os.mkdir(“test”)
删除文件夹:os.rmdir(“test”)
获取当前路径:os.getcwd()
改变默认目录:os.chdir(“../”)
获取目录列表:os.listdir(“./”)
10.批量重命名代码import os
#1.获取要重命名的文件夹 名字
folder_name = input("请输入要重命名的文件夹:")
#2.获取指定的文件夹中的所有 文件名字
file_names= os.listdir(folder_name)
os.chdir(floder_name)
#3.重命名
for name in file_names:
print(name)
old_file_name= folder_name+"/"+name
new_file_name= folder_name+"/"+"[京东出品]-"+name
os.rename(old_file_name,new_file_name)
面向对象
1. 面向对象和面向过程的区别
面向过程:根据业务逻辑从上到下写代码
面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程(能让程序更加简单,更加紧凑 面向对象和面向过程都是解决问题的一种思路而已
面向对象(object-oriented;简称:OO) 至今还没有统一的概念我这里把它定义为:按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。面向对象编程(ObjectOriented Programming-OOP) 是一种 解决软件复用的设计和编程方法。这种方法把软件系统中相近相似的操作逻辑和操作应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高 软件开发效率的作用。
2.类和对象的关系
面向对象编程的2个非常重要的概念:类和对象
- 对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类
- 类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象
- 类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在,一个类可以找到多个对象。某一个具体事物的存在,在现实世界中可以是看得见摸得着的,可以是直接使用的
简单的说,类可以看成是一个模型,是创建对象的一个模型,而对象就是一个实物,类的范围比对象大
3.类的构成类的名称:类名
类的属性:一组数据
类的方法:允许对进行操作的方法(行为)
新式类:广度优先,从最接近的上一个类开始,依次往上寻找相应的继承属性旧式类:深度优先,从最开始的类开始,依次往下寻找相应的继承属性
4.类的抽象
拥有相同(或者类似)属性和行为的对象都可以抽像出一个类
5.定义类class类名(推荐大驼峰命名法):
#属性#方法
defxxx(self): #注意在定义行为的时候要用self
pass
6.创建一个对象
在上述的代码之后,加上tom= 类名,返回对象的引用tom.drink()引用drink的行为
添加变量:tom.color= “黑色”
7.self:
如在lanmao.introduce()中,print(“self.name”),谁调用就指向谁,它就会介绍自己 lanmao
8.类里面的方法和函数的区别
类里的方法和函数外观很相似,都采用def hanshu(),但是类的方法里必须要有一个 形参,它可以是self,可以是a,b,c,d等等,但是在调用的时候,实参里不能传递任何值
9.__init__方法(给对象添加特定的属性)
def__init__(self):python会自动调用这一个方法,一旦创建即可默认调用,这种方法通常被称为魔法 方法
利用好这一点,就可以用它来传递一些特定的属性,不用每个对象都去定义一遍
例如:def__init__(self,new_name,new_age)
self.name= new_name
self.age = new_age
最后在创建对象的时候注意把这个属性参数传递进去,只有在创建对象的时候可以扔 参数,对象发生行为时不可以扔参数:
tom =Cat(“tom”,18)
10.__str__方法(返回调用对象的信息)def__str__(self):
同__init__方法一样,一旦创建即可调用,常被用来返回对象的信息
例如:def__str__(self):
return “%s的年龄是:%s”%(self.name,self.age)
print(tom) #打印对象的信息
11.应用-烤地瓜
如果当多次调用某个方法,要方法的下一次调用用到上一次的结果,不应该在这个方 法里找一个变量存,因为这个方法一旦被调用完后,就会释放内存,正确的方法是要找 到当前对象的一个属性,把这个结果扔到属性里去如果一种属性需要多个元素,可以引入列表来存储多个数值,在__str__()方法中的return可以直接利用str(self.condiments))返回这个列表的信息
12.应用-存放家具
如果一个对象与另外一个对象有一定的关系,那么一个对象可用是另外一个对象的 属性如果要是能用直接获取属性的地方,统统改成用方法来获取,因为这样可以避免直 接被访问的情况,遇到不想被访问的信息时候做不到禁止,权限控制
13.逻辑属性要用方法来赋值
在给对象设置属性的时候,如果直接赋予的话,可能某种情况下会发生不合逻辑的情况,如dog.age = -10,这句话语法是没有错的,所有在运行的时候不会报错,所有最好是在设置属性的时候,用方法来赋值,这样可以引入判断,如if new_age >0: self.age = new_age,这样就能使得属性符合人们的逻辑了
14.公有方法和私有方法
私有方法:如def __send_msg():这个方法一般表示是比较重要的方法,且一般需要获得一定条件才可调用,称为是私有方法,即需要满足一一定条件,就好比是发短信一样,需要有金额大于0的情况下,但在property装饰的方法可以访问私有化的实例属性,所有封装的确不是让人看不见
公有方法:如def send_msg():这就是公有方法,即调用就可以执行,公有方法还可以去调用私有方法,当满足一定的情况,可以调用私有方法,这就是私有方法的使用
私有的属性:不能通过对象直接访问,但能通过方法访问,私有的方法只能通过方法访问
15.__del__方法
如果对象在程序结束之前把所有引用都删了,del方法在最后一个删的时候结束,触发调用del方法,但如果并没有删除完所有的引用,也就是程序还有占用内存,那么在程序结束之后再触发这个del方法
16.测量对象的引用个数
如果要测量一个对象的引用计数的方式,那么就要导入sys模块,采用sys模块里的sys.getrefcount(对象),就会返回一个值,因为在使用这个模块方法时会自动使用一个变量把这个对像引用值保存起来,所以返回值要比实际引用个数多1
17.单继承
继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物,一般程序都称为父类(基类)和子类(派生类),没有母类
子类在继承的时候,在定义类时,小括号()中为父类的名字,如class Animal(object): class Dog(Animal):这就是一个简单的继承,子类(派生类)可以使用所有父类(基类)的方法,但不能使用同一基类下其他派生类的方法
注意:在继承的过程中,父类的私有属性,私有方法,也就是由双下划线__test():组成的不能继承继承的意义与好处:
- 可以实现代码复用,但也不是全部复用,可能不用
- 实现属性和方法继承
子类可以有多个父类,就好像骡子既继承类马又继承类驴。这里的多继承指的是子类可以继承父类的父类,也可以继承来自不同的父类,例如class C(A,B):
上面的多继承例子中,如果父类A和父类B中,有一个同名的方法,那么通过子类去调用的时候,调用哪个?
调用的先后顺序:先调用自己的方法,如果没有就从上一个先定义的父类找,再下一个父类,如果还是还找不到就是父类的父类,再没有就错误了
如果调用的是继承的父类中的公有方法,可以在这个公有方法中访问父类的私有属性和私有方法,但是,如果在子类中实现了一个公有方法,那么这个方法不能够调用继承的父类中的私有方法和私有属性
19.重写重写就是把方法与父类同样的定义一遍
如果发现在继承的时候,父类的方法的名字就是想要的名字,但不是想要的功能的时候,那么这个时候就可以去重写,如果子类中有这个方法的名字,那么它就会执行这个类里的方法,如果没有这个方法的时候才会去父类里找
20.调用被重写的方法
在重写的方法里去调用被重写的部分
第一种:Dog.bark(self)
第二种:super().bark()
关于代码#super().__init__()的说明这一行代码,可以调用也可以不调用,建议调用,因为__init__方法往往是用来对创建完的对象进行初始化工作,如果在子类中重写了父类的__init__方法,即意味着父类中的很多初始化工作没有做,这样就不保证程序的稳定了,所以在以后的开发中,如果重写了父类的__init__方法,最好是先调用父类的这个方法,然后再添加自己的功能
21.多态
简单的说,一个人有多种表现形式就是多态是指面向对象程序执行时,相同的信息可能会送给多个不同的类别对象,系统可根据对象所属类别,引发对应类别方法而有不同的行为
所谓多态:定义时的类型和运行时的类型不一样,此时就称为多态,简单的说就是根据对象的不同来执行不一样的功能,如:
def introduce(temp):
temp.print_self()
这里就根据temp的不同来执行各自的print_self,这就是多态,这个print_self就是不同类里的一个方法
22.类属性,实例属性
类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成类外可以通过类对象和实例对象访问,也就是说类对象好比是一张大的海报,人人都能看,实例属性就是对象的基本属性员变量有点类似。对于公有的类属性,在,好比是人人都有一张海报,浪费资源,所有就有了类属性,可以被所有类对象和实例对象访问,就好比是实例对象的共享属性称为类属性,只需要创建一次实例属性不能左右类属性,但类属性能影响实例属性,但如果是变量引起的是一个可变的对象-列表,则通过类属性和实例属性都能直接改变这个对象
调用时用类名+类属性,例:Tool.num +=1
在给类添加属性的时候,该属性被放入类对象的__dict__魔法字典的键值对中
在给实例添加属性的时候,该属性被放入实例对象的__dict__魔法字典的键值对中
23.类方法,静态方法类方法:是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,类方法还有一个用途就是可以对类属性进行修改,它不能访问实例属性
两种调用方式:对类属性操作用类方法第一种:通过类的名字调用类方法,如Game.add_num()
第二种:通过类创建出来的对象去调用这个类方法,如game.add_num()
静态方法:需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数,它无法访问实例变量,类,和实例属性
两种调用方式:方法与类关系和实例方法没有关系,就用静态方法
第一种:通过类的名字调用静态方法,如Game.print_menu()
第二种:通过类创建出来的实例对象去调用静态方法,如game.print_menu()
方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用
24.耦合性
如果类与类之间的耦合性过强,也就是一个类改变,另一个类也需要改变,此时可以定义一个函数,把其中一个类的方法形参传递到这个函数中,再在这个函数里返回到类中,如设计4s店类例子,这种思维叫做解耦
但是如果采用面向对象编程就最好全部采用对象编程,于是这个方法就要定义为一个类,分离其他两个类的方法叫做简单工厂模式
基类只是搭一个框架,不需要实现所有功能,功能在子类里实现
25.工厂方法模式定义了一个创建对象的接口(可以理解为函数),但由子类决定要实例化的类是哪一个,工厂方法模式让类的实例化推迟到子类,抽象的CarStore提供了一个创建对象的方法createCar,也叫作工厂方法。
子类真正实现这个createCar方法创建出具体产品。 创建者类不需要直到实际创建的产品是哪一个,选择了使用了哪个子类,自然也就决定了实际创建的产品是什么
26.__new__方法
定义def __new__(cls):
return object.__new__(cls)
__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例, __new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法
简单的说__init__只负责初始化,__new__只负责创建,他们两结合的方法就是构造方法
27.单例对象
就是不管怎么创建,始终只有一个对象,就是单例 ,就要在用一个类属性来判断是否已经创建了对象,如果创建了对象就把它保存起来再返回出去,if cls.__instance == None:如果没有,就让cls.__instance = object.__new__(cls)
28.只初始化一次对象
与上述类似,加一个类属性判断即可,__init_flag = false就初始化,然后__init_flag=True,就不会执行初始化
29.内置命名空间,全局命名空间,本地命名空间
内置命名空间:python运行起来,它们就存在了。内置函数的命名空间都属于内置命名空间,所以我们可以在任何程序中直接运行它们,比如前面的id(),不需要什么操作,拿过来就能用全局命名空间:每个模块创建它自己所拥有的全部命名空间,不同模块的全局命名空间彼此独立,不同模块中相同名称的命名空间,也会因为模块的不同步相互干扰
本地命名空间:模块中有函数或者类,每个函数或者类所定义的命名空间就是本地命名空间,如果函数返回了结果或者抛出异常,则本地命名空间也结束了
异常
1.异常当Python检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓"异常"
try: (放置可能出现错误的代码)(这是可以嵌套的)
print(num)print("-----1-----")
except NameError as ret:(如果产生错误,处理的方法,当捕获多个异常时,可以把要捕获的异常的名字,放到except 后,并使用元组的方式仅进行存储)(也可以用except Exception)
print("处理异常")
print(ret)(获取异常的信息描述)
else: (没有异常才会执行的功能)print("没有异常")
finally:(在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally)print("------")
2.异常的传递
如果一个异常是在一个函数中产生的,例如函数A---->函数B---->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推。。。如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样
3.自定义异常
用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类
4.异常处理中抛出异常
直接默认raise
5.assert语句
assert,翻译过来是断言,assret是语句等价于布尔真的判断,发生异常就意味着表达式为假,如assert amount >0,amount必须大于零的情况下就用断言,当条件不满需就会报错
用于如下情况:- 防御性的编程
- 运行时对程序逻辑的检测
- 合约性检查(比如前置条件,后置条件)
- 程序中的常量
- 检查文档
python的面向对象的三个基本要素:封装,继承,多态
模块
1.模块的介绍
Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块
2.制作模块
比如现在test.py中,定义了函数add,然后新建一个sendmsg.py,在里面导入import test,使用test.add(),也可以用from test import sendmsg,调用test()就是一个制作模块的大体流程,为了让我们自己写的模块被python解释器知道,需要用sys,path.append("路径"),但这种情况下,比如在交互模式下,如果关闭了,再开启,还要重新告知
常用方法:设置PYTHONPATH环境变量vim /etc/profile
export PATH = /home/jack/python:$PAT
3.延时
import time as tt(可以起个乳名,意在替代当模块名过长的情况)time.sleep(5) #延时5秒
4.__all__
from test import *时,为了防止把不需要的模块导入,在模块里边新建一个变量__all__,是一个列表,放上将来要使用的函数,类,全局变量的名字,如果不放,别人就无法使用 __all__ =["Tset","test"] ,
5. __name__
有时候在代码的编写过程中,肯定会在代码里面加入测试的代码,那么在引入这个模块的时候就会发生每一次引入的时候这些测试代码就会运行,但是在真正使用的过程中是不需要测试代码的实现的,所以需要有一种方法可以既能实现代码的测试,又不会在引入模块的时候被执行,就需要在模块里加入if __name__ = "__main__()":,在这个条件下执行不会引入测试代码,但是在模块本身又能完成测试,如果只是用于导入模块,则不需要这个
6.python中的包
包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py 文件,那么这个文件夹就称之为包,这个__init__.py控制着包的导入行为,在这个文件中, 定义一个__all__变量,它控制着 from 包名 import *时导入的模块,如__all__ = ["sendmsg"]
7.模块发布1.编辑setup.py:
from distutils.core import setup
setup(name="dongGe", version="1.0", description="dongGe's module", author="dongGe", py_modules=['test.sendmsg', 'test.recvmsg'])
2.构建模块
python/python3 setup.py build
3.生成发布压缩包python/python3 setup.py sdist
8.模块安装,使用
1.找到模块的压缩包2.解圧
3.进入文件夹
4.执行命令python setup.py install
5.模块的引入
from 模块名 import 模块名或者*
9.给程序传参数
import sysprint(sys.argv)
name = sys.argv[1]
print("热烈欢迎%s的到来"%name)
9.列表推导式
range的风险是在python2里,如果是[1,10000000]会占用很大的内存,而在python3中不会出现这个情况,需要的时候立刻生成一个值供使用
1.while 的列表推导name = []
i=0
while i<=77:
name.append(i)
i+=1
print (name)
2.for的列表推导,range与切片很类似
for i in range(10,78):
print(i)
3.第一个i是元素的值,后面的for是代表循环的次数,如果第一个i=11,那么所有的元素都是11
a=[i for i in range(1,18)]
print(a)
4. #for控制循环的次数,for和if的嵌套
c = [i for i in range(10) if i%2==0]
print(c)
5. #每执行第一个for循环都要执行第二个循环的所有次数
d = [i for i in range(3) for j in range(2)]
print(d)
6.#每执行第一个for循环都要执行第二个循环的所有次数
d = [(i,j) for i in range(3) for j in range(2)]
print(d)
例题:找出100以内能被3整除的正整数
aiquot = [] 很简洁:range(3,100,3)
for n in range(1,100)
if n%3 ==0:
aiquot.append(n)
10.import math和from math import *的区别
如:import math from math import *
math.pow(3,2) pow(3,2)
调用math模块的math.pow函数 这里不需要加上math的前缀
10.set,list,tuple
set的类型是集合,set,list,tuple之间可以互相转换
d=list(c) d=tuple(c) d=set(e)
使用set,可以快速的完成对list中的元素去重复功能