1 hello world
#-*- coding:utf-8 -*- #这个是为了说明文件的编码方式,不可缺少,也可以用#coding=utf-8
#单行注释
print("hello world")
#多行注释'''
'''
print("hello world")
print("hello world")
'''
优点
- 简单
- 易学
- 免费、开源
- 高层语言————当你用Python语言编写程序的时候,你无需考虑诸如如何管理你的程序使用的内存一类的底层细节。
- 可移植性————由于它的开源本质,Python已经被移植在许多平台上(经过改动使它能够工作在不同平台上)。
- 解释性————这一点需要一些解释。一个用编译性语言比如C或C++写的程序可以从源文件(即C或C++语言)转换到一个你的计算机使用的语言(二进制代码,即0和1)。这个过程通过编译器和不同的标记、选项完成。当你运行你的程序的时候,连接/转载器软件把你的程序从硬盘复制到内存中并且运行。而Python语言写的程序不需要编译成二进制代码。你可以直接从源代码运行程序。在计算机内部,Python解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成计算机使用的机器语言并运行。事实上,由于你不再需要担心如何编译程序,如何确保连接转载正确的库等等,所有这一切使得使用Python更加简单。由于你只需要把你的Python程序拷贝到另外一台计算机上,它就可以工作了,这也使得你的Python程序更加易于移植。
- 面向对象
- 可扩展性————如果你需要你的一段关键代码运行得更快或者希望某些算法不公开,你可以把你的部分程序用C或C++编写,然后在你的Python程序中使用它们。
- 丰富的库
- 规范的代码
基础知识
输出与格式化:
print("我的姓名是%s,年龄是%d"%(name,age))
输入:
password = input("请输入密码:")
或者python2的password = raw_input("请输入密码:")
-
常用的数据类型转换
函数 说明 int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 complex(real [,imag ]) 创建一个复数 str(x ) 将对象 x 转换为字符串 repr(x ) 将对象 x 转换为表达式字符串 eval(str ) 用来计算在字符串中的有效Python表达式,并返回一个对象 tuple(s ) 将序列 s 转换为一个元组 list(s ) 将序列 s 转换为一个列表 chr(x ) 将一个整数转换为一个字符 unichr(x ) 将一个整数转换为Unicode字符 ord(x ) 将一个字符转换为它的整数值 hex(x ) 将一个整数转换为一个十六进制字符串 oct(x ) 将一个整数转换为一个八进制字符串 逻辑运算符
and
or
not
双引号或者单引号中的数据,就是字符串
列表与元组支持下标索引好理解,字符串实际上就是字符的数组,所以也支持下标索引。所以可以直接获取字母 ,如
print(name[0])
字符串切片,是指对操作的对象截取其中一部分的操作,如
print(name[0:3]) # 取 下标0~2 的字符
print(name[1:-1]) # 取 下标为1开始 到 最后第2个 之间的字符
字符串常用操作
方法 | 说明 | 示例 |
---|---|---|
find | 检测 str 是否包含在 mystr中,如果是返回开始的索引值,否则返回-1 | mystr.find(str, start=0, end=len(mystr)) |
index | 跟find()方法一样,只不过如果str不在 mystr中会报一个异常. | mystr.index(str, start=0, end=len(mystr)) |
count | 返回 str在start和end之间 在 mystr里面出现的次数 | mystr.count(str, start=0, end=len(mystr)) |
replace | 把 mystr 中的 str1 替换成 str2,如果 count 指定,则替换不超过 count 次 | mystr.replace(str1, str2, mystr.count(str1)) |
split | 以 str 为分隔符切片 mystr,如果 maxsplit有指定值,则仅分隔 maxsplit 个子字符串 | mystr.split(str=" ", 2) |
capitalize | 把字符串的第一个字符大写 | mystr.capitalize() |
title | 把字符串的每个单词首字母大写 | |
startswith | 检查字符串是否是以 obj 开头, 是则返回 True,否则返回 False | mystr.startswith(obj) |
endswith | 检查字符串是否以obj结束,如果是返回True,否则返回 False. | mystr.endswith(obj) |
lower | 转换 mystr 中所有大写字符为小写 | mystr.lower() |
upper | 转换 mystr 中的小写字母为大写 | mystr.upper() |
ljust | 返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串 | mystr.ljust(width) |
rjust | 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串 | mystr.rjust(width) |
center | 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 | mystr.center(width) |
lstrip | 删除 mystr 左边的空白字符 | mystr.lstrip() |
rstrip | 删除 mystr 字符串末尾的空白字符 | mystr.rstrip() |
strip | 删除mystr字符串两端的空白字符 | |
rfind | 类似于 index(),不过是从右边开始. | mystr.rindex( str, start=0,end=len(mystr)) |
partition | 把mystr以str分割成三部分,str前,str和str后 | mystr.partition(str) |
rpartition | 类似于 partition()函数,不过是从右边开始. | mystr.rpartition(str) |
splitlines | 按照行分隔,返回一个包含各行作为元素的列表 | mystr.splitlines() |
isalpha | 如果 mystr 所有字符都是字母 则返回 True,否则返回 False | mystr.isalpha() |
isdigit | 如果 mystr 只包含数字则返回 True 否则返回 False. | mystr.isdigit() |
isalnum | 如果 mystr 所有字符都是字母或数字则返回 True,否则返回 False | mystr.isalnum() |
isspace | 如果 mystr 中只包含空格,则返回 True,否则返回 False. | mystr.isspace() |
join | mystr 中每个字符后面插入str,构造出一个新的字符串 | str.join(mystr) |
- 列表
testList = [1, 'a']
- 列表常用方法
方法 | 说明 |
---|---|
append | 向列表添加元素 |
extend | 将另一个集合中的元素逐一添加到列表中 |
insert | insert(index, object) 在指定位置index前插入元素object |
修改元素 | 通过下标来确定要修改的是哪个元素,然后才能进行修改 |
in(存在) | 如果存在那么结果为true,否则为false |
not in(不存在) | 如果不存在那么结果为true,否则false |
index | 检测 str 是否包含在列表中,如果是返回开始的索引值,否则返回-1 |
count | 返回 str在start和end之间 在 mystr里面出现的次数 |
del | 根据下标进行删除 |
pop | 删除最后一个元素 |
remove | 根据元素的值进行删除 |
sort | 将list按特定顺序重新排列,默认为由小到大,参数reverse=True可改为倒序,由大到小。 |
reverse | 将list逆置 |
- 列表的嵌套
schoolNames = [['北京大学','清华大学'], ['南开大学','天津大学','天津师范大学'], ['山东大学','中国海洋大学']]
- 元组,Python的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。
aTuple = ('et',77,99.9)
- 字典,
info = {'name':'班长', 'id':100, 'sex':'f', 'address':'地球亚洲中国北京'}
,print(info['name'])
,info.get('age', 18)
- 字典常用操作
方法/方式 | 说明 |
---|---|
使用 变量名['键'] = 数据 | 这个“键”在字典中,不存在,那么就会新增这个元素,否则就是修改 |
del | del info['name'] 删除一个元素 del info 删除整个字典 |
clear() | 清空 info.clear() |
len() | 测量字典中,键值对的个数 |
keys | 返回一个包含字典所有KEY的列表 |
values | 返回一个包含字典所有value的列表 |
items | 返回一个包含所有(键,值)元祖的列表 |
dict.has_key(key) | 如果key在字典中,返回True,否则返回False |
for key,value in dict.items() | 遍历字典的key-value(键值对) |
-
如何实现带下标索引的遍历 --enumerate()
>>> chars = ['a', 'b', 'c', 'd'] >>> for i, chr in enumerate(chars): ... print i, chr ... 0 a 1 b 2 c 3 d
列表表达式快速生成列表
a = [ x for x in rang(4)]
a
Out[4]: [0, 1, 2, 3]
b = [x for x in range(3, 10) if x%2!=0]
b
Out[6]: [3, 5, 7, 9]
c = [(x, y, z) for x in range(1,3) for y in range(3) for z in range(4,6)]
c
Out[8]:
[(1, 0, 4),
(1, 0, 5),
(1, 1, 4),
(1, 1, 5),
(1, 2, 4),
(1, 2, 5),
(2, 0, 4),
(2, 0, 5),
(2, 1, 4),
(2, 1, 5),
(2, 2, 4),
(2, 2, 5)]
set、list、tuple方法与转换
eg:
a = set()
type(a)
Out[3]: set
b = list()
type(b)
Out[5]: list
c = tuple()
type(c)
Out[8]: tuple
a = {1,2,3}
b = [1,2,2,2,2,4]
c = (1,2,3,4)
a
Out[12]: {1, 2, 3}
b
Out[13]: [1, 2, 2, 2, 2, 4]
c
Out[14]: (1, 2, 3, 4)
d = list(c) # tuple -> list
d
Out[16]: [1, 2, 3, 4]
e = set(b) #list->set 有去重的效果
e
Out[18]: {1, 2, 4}
公共方法
运算符
运算符 | Python 表达式 | 结果 | 描述 | 支持的数据类型 |
---|---|---|---|---|
+ | [1, 2] + [3, 4] | [1, 2, 3, 4] | 合并 | 字符串、列表、元组 |
* | 'Hi!' * 4 | ['Hi!', 'Hi!', 'Hi!', 'Hi!'] | 复制 | 字符串、列表、元组 |
in | 3 in (1, 2, 3) | True | 元素是否存在 | 字符串、列表、元组、字典 |
not in | 4 not in (1, 2, 3) | True | 元素是否不存在 | 字符串、列表、元组、字典 注意,in在对字典操作时,判断的是字典的键 |
python内置函数
Python包含了以下内置函数
序号 | 方法 | 描述 |
---|---|---|
1 | cmp(item1, item2) | 比较两个值 |
2 | len(item) | 计算容器中元素个数 |
3 | max(item) | 返回容器中元素最大值 |
4 | min(item) | 返回容器中元素最小值 |
5 | del(item) | 删除变量 |
cmp
注意:cmp在比较字典数据时,先比较键,再比较值。
del
del有两种用法,一种是del加空格,另一种是del()
多维列表/元组访问的示例
>>> tuple1 = [(2,3),(4,5)]
>>> tuple1[0]
(2, 3)
>>> tuple1[0][0]
2
>>> tuple1[0][2]
引用
rentianxin@rentianxin-Desk /m/r/s/h/v/huaqin> ipython
In [1]: a = 100
In [2]: b = a
In [3]: id(a)
Out[3]: 12146592
In [4]: id(b)
Out[4]: 12146592
In [5]: A = [11,22,33]
In [6]: B = A
In [7]: id(A)
Out[7]: 140151283711584
In [8]: id(B)
Out[8]: 140151283711584
In [9]: A.append(44)
In [10]: A
Out[10]: [11, 22, 33, 44]
In [11]: B
Out[11]: [11, 22, 33, 44]
在python中,值是靠引用来传递来的。只要出现=
那一定是引用赋值。对于空引用的内存空间,会被垃圾回收器回收。
可以用is()判断两个引用所指的对象是否相同
可以用id()来获取变量的引用地址。 我们可以将id值理解为那块内存的地址标示。
可变类型与不可变类型
可变类型/引用类型 ,定义了之后值可以改变:
- 列表 list
- 字典 dict
不可变类型/值类型,定义了之后值就不可以再改变了:
- 数值类型 int, long, bool, float
- 字符串 str --字符串定义后,里面的字符就不可以单独更改了
- 元组 tuple
函数
在函数外边定义的变量叫做
全局变量
全局变量能够在所有的函数中进行访问
-
如果在函数中修改全局变量,那么就需要使用
global
进行声明,否则出错a = 1 def f(): global a#不加这句话就会报错 a += 1 print a
如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的
函数多返回值
sh, yu = divid(5, 2)
, 本质是使用元组
缺省参数
def printinfo( name, age = 35 ):
注意:带有默认值的参数一定要位于参数列表的最后面。
不定长参数
基本语法如下:
def functionname([formal_args,] *args, **kwargs):
"函数_文档字符串"
function_suite
return [expression]
#例如:
def fun(a, b, *args, **kwargs):
"""可变参数演示示例"""
print "a =", a
print "b =", b
print "args =", args
print "kwargs: "
for key, value in kwargs.items():
print key, "=", value
#结果如下
#args = (3, 4, 5)
#kwargs:
#p = 8
#m = 6
#n = 7
#例如
c = (3, 4, 5)
d = {"m":6, "n":7, "p":8}
fun(1, 2, *c, **d) # 注意元组与字典的传参方式
加了星号()的变量args会存放所有未命名的变量参数,args为元组;而加*的变量kwargs会存放命名参数,即形如key=value的参数, kwargs为字典。
都是引用传参
Python中函数参数是引用传递(注意不是值传递)。对于不可变类型,因变量不能修改,所以运算不会影响到变量自身;而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量。
>>> a_int = 1 #定义了全局变量,假设地址为#0001
>>> def selfAdd(a):# 第一次调用a-> #0001 # 第二次调用a->#0008
... """自增"""
... a += a #a 是不可变类型,不能修改,所以1+1 = 2 ,假设地址为 #0004,所以a -> #0004
# a 是可变类型,+=是直接对#0008的控件进行修改,由[1,2] 变成[1, 2, 1, 2] ,所以a ->#0006,但是#0006这片空间的内容被改变了
...
>>> a_int#0001的值
1
>>> selfAdd(a_int)
>>> a_int#0001的值
1
>>> a_list = [1, 2] #假设地址为#0006
>>> a_list #0006的值
[1, 2]
>>> selfAdd(a_list) #传入#0006
>>> a_list #0006的值
[1, 2, 1, 2]
>>> a_int = 1 #定义了全局变量,假设地址为#0001
>>> def selfAdd(a):# 第一次调用a-> #0001 # 第二次调用a->#0006
... """自增"""
... a = a + a # 我们更改了函数体的这句话
#第一次调用 a 是不可变类型,不能修改,所以1+1 = 2 ,假设数值2所在的地址为 #0004,所以a -> #0004
# a 是可变类型,先执行a + a,由[1,2] 变成[1, 2, 1, 2] ,假设地址为#0008,所以a ->#0008
...
>>> a_int#0001的值
1
>>> selfAdd(a_int)
>>> a_int#0001的值
1
>>> a_list = [1, 2]#假设地址为#0006
>>> a_list ##0006的值
[1, 2]
>>> selfAdd(a_list)
>>> a_list##0006的值
[1, 2]
理解:
python中对方法参数的赋值都是引用赋值
-
a+=a =/= a= a + a 不完全相等
注意和java中的值传递和引用传递做区别参考值传递与引用传递
匿名函数
用lambda关键词能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤。
lambda函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
如下实例:
sum = lambda arg1, arg2: arg1 + arg2
#调用sum函数
print "Value of total : ", sum( 10, 20 )
应用场合
函数作为参数传递
>>> def fun(a, b, opt):
... print "a =", a
... print "b =", b
... print "result =", opt(a, b)
...
>>> fun(1, 2, lambda x,y:x+y)
a = 1
b = 2
result = 3
作为内置函数的参数
例如列表的排序参数
stus.sort(key = lambda x:x['age'])
注意事项:
- 函数名不能重复,因为没有重载函数的说法,不同参数的函数可以用缺省参数实现
- 调用时,实参的个数和先后顺序应该和定义函数中要求的一致
- 注意变量作用域
文件操作
open(文件名,访问模式)
# 新建一个文件,文件名为:test.txt
f = open('test.txt', 'w')
f.write('hello world, i am here!')
# 关闭这个文件
f.close()
文件的读写
- 使用write()可以完成向文件写入数据,如果文件不存在那么创建,如果存在那么就先清空,然后写入数据(具体看访问模式)
- 使用
read(num)
可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
- 如果open是打开一个文件,那么可以不用写打开的模式,即只写
open('test.txt')
- 如果使用读了多次,那么后面读取的数据是从上次读完后的位置开始的
方法 | 描述 | 使用 | 注意 |
---|---|---|---|
write() | 向文件写入数据 | f.write('hello world, i am here!') | 如果文件不存在那么创建,如果存在那么就先清空,然后写入数据 |
read(num) | 从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据 | content = f.read(5) | 如果使用读了多次,那么后面读取的数据是从上次读完后的位置开始的 |
readlines | readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素 | content = f.readlines() print(type(content)) i=1 for temp in content: print("%d:%s"%(i, temp)) i+=1 |
获取当前读写的位置
方法 | 描述 | 使用 |
---|---|---|
tell() | 在读写文件的过程中,如果想知道当前的位置,可以使用tell()来获取 | # 查找当前位置 position = f.tell() print "当前文件位置 : ", position |
seek(offset, from) | 如果在读写文件的过程中,需要从另外一个位置进行操作的话,可以使用seek() seek(offset, from)有2个参数 offset:偏移量 from:方向 0:表示文件开头 1:表示当前位置 2:表示文件末尾 | # 重新设置位置,从文件开头,偏移5个字节 f.seek(5,0) |
文件的重命名、删除
方法 | 描述 | 使用 |
---|---|---|
rename(需要修改的文件名, 新的文件名) | os模块中的rename()可以完成对文件的重命名操作 | import os os.rename("毕业论文.txt", "毕业论文-最终版.txt") |
remove(待删除的文件名) | os模块中的remove()可以完成对文件的删除操作 | import os os.remove("毕业论文.txt") |
文件夹的相关操作
方法 | 描述 | 使用 |
---|---|---|
mkdir | 创建文件夹 | import os os.mkdir("张三") |
getcwd() | 获取当前目录 | import os os.getcwd() |
chdir() | 改变默认目录 | import os os.chdir("../") |
listdir | 获取当前文件夹下所有文件(包括文件夹)的名称 | import os os.listdir("./") |
rmdir | 删除文件夹 | import os os.rmdir("张三") |
os.walk(top, topdown=True, onerror=None, followlinks=False) | 文件遍历 dirpath 是一个string,代表目录的路径, dirnames 是一个list,包含了dirpath下所有子目录的名字。 filenames 是一个list,包含了非目录文件的名字。 这些名字不包含路径信息,如果需要得到全路径,需要使用os.path.join(dirpath, name). | for root, dirs, files in os.walk(file_dir): print(root) #当前目录路径 print(dirs) #当前路径下所有子目录 print(files) #当前路径下所有非目录子文件 |
面向对象
class Car:
def __init__(self):#在创建对象后,就立刻被默认调用了
self.wheelNum = 4
self.color = '蓝色'
#def __init__(self,name):
# self.name = name
# self.xue = 100
# self.qiang = None
def move(self):
print('车在跑,目标:夏威夷')
def printName(self):
print('名字为:%s'%self.name)
#def anzidan(self,danjia,zidan):
# danjia.baocunzidan(zidan)
# 创建对象
BMW = Car()
print('车的颜色为:%s'%BMW.color)
print('车轮胎数量为:%d'%BMW.wheelNum)
“魔法”方法
def __str__(self): #相当于java的toString()方法
msg = "嘿。。。我的颜色是" + self.color + "我有" + int(self.wheelNum) + "个轮胎..."
return msg
#__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
def __new__(cls):
print("这是 new 方法")
return object.__new__(cls)
def __init__(self):
print("这是 init 方法")
#构造方法
def __init__(self):#在创建对象后,就立刻被默认调用了
self.wheelNum = 4
self.color = '蓝色'
# 析构方法
# 当对象被删除时,会自动被调用
# 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
#当使用del删除变量指向的对象时,如果对象的引用计数不是1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除
def __del__(self):
print("__del__方法被调用")
print("%s对象马上被干掉了..."%self.__name)
__new__和__init__
的作用
-
__new__
至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供 -
__new__
必须要有返回值,返回实例化出来的实例,这点在自己实现__new__
时要特别注意,可以return父类__new__
出来的实例,或者直接是object的__new__
出来的实例 -
__init__
有一个参数self,就是这个__new__
返回的实例,__init__
在__new__
的基础上可以完成一些其它初始化的动作,__init__
不需要返回值 - 我们可以将类比作制造商,
__new__
方法就是前期的原材料购买环节,__init__
方法就是在有原材料的基础上,加工,初始化商品环节
私有属性
def __init__(self, name):
self.__name = name
- Python中没有像C++中public和private这些关键字来区别公有属性和私有属性
- 它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。
继承
class C(A,B):# class C 继承子A和B,私有的属性、方法,不会被子类继承,也不能被访问
#coding=utf-8
class Cat(object):
def sayHello(self):
print("halou-----1")
def __init__(self,name):
self.name = name
self.color = 'yellow'
class Bosi(Cat):
#重写父类的构造方法
def __init__(self,name):
# 调用父类的__init__方法1(python2)
#Cat.__init__(self,name)
# 调用父类的__init__方法2
#super(Bosi,self).__init__(name)
# 调用父类的__init__方法3
super().__init__(name)
#重写父类方法
def sayHello(self):
print("halou-----2")
bosi = Bosi()
bosi.sayHello()
多态
多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态
- Python伪代码实现Java或C#的多态
class F1(object):
def show(self):
print 'F1.show'
class S1(F1):
def show(self):
print 'S1.show'
class S2(F1):
def show(self):
print 'S2.show'
# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象
def Func(F1 obj):
"""Func函数需要接收一个F1类型或者F1子类的类型"""
print obj.show()
s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
s2_obj = S2()
Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
- Python “鸭子类型”
class F1(object):
def show(self):
print 'F1.show'
class S1(F1):
def show(self):
print 'S1.show'
class S2(F1):
def show(self):
print 'S2.show'
def Func(obj):
print obj.show()
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
类属性、实例属性
class People(object):
name = 'Tom' #公有的类属性
__age = 12 #私有的类属性
p = People()
print(p.name) #正确
print(People.name) #正确
print(p.__age) #错误,不能在类外通过实例对象访问私有的类属性
print(People.__age) #错误,不能在类外通过类对象访问私有的类属性
类属性就是类对象
所拥有的属性,它被所有类对象
的实例对象
所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,在类外可以通过类对象
和实例对象
访问。
如果需要在类外修改类属性
,必须通过类对象
去引用然后进行修改。
静态方法和类方法
1. 类方法
是类对象所拥有的方法,需要用修饰器@classmethod
来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls
作为第一个参数,能够通过实例对象和类对象去访问。
类方法可以获取类属性也可以对类属性进行修改:
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
p = People()
print p.getCountry() #可以用过实例对象引用
print People.getCountry() #可以通过类对象引用
p.setCountry('japan')
print p.getCountry()
print People.getCountry()
2. 静态方法
需要通过修饰器@staticmethod
来进行修饰,静态方法不需要多定义参数
class People(object):
country = 'china'
@staticmethod
#静态方法
def getCountry():
return People.country
print People.getCountry()
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用
单例模式
# 实例化一个单例
class Singleton(object):
__instance = None
def __new__(cls, age, name):
#如果类数字能够__instance没有或者没有赋值
#那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时
#能够知道之前已经创建过对象了,这样就保证了只有1个对象
if not cls.__instance: #如果对象不存在
cls.__instance = object.__new__(cls)
return cls.__instance
# 实例化一个单例
class Singleton(object):
__instance = None
__first_init = False
def __new__(cls, age, name):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self, age, name):
if not self.__first_init: # 如果是第一次加载,则执行一次__init__
self.age = age
self.name = name
Singleton.__first_init = True
异常
#coding=utf-8
try:
open('123.txt','r') # 如果123.txt文件不存在,那么会产生 IOError 异常
print('-----test--2---')
print(num)# 如果num变量没有定义,那么会产生 NameError 异常
except (IOError,NameError):
#如果想通过一次except捕获到多个异常可以用一个元组的方式
# errorMsg里会保存捕获到的错误信息
print(errorMsg)
#coding=utf-8
try:
num = 100
print num
except NameError as errorMsg:
print('产生错误了:%s'%errorMsg)
else:
print('没有捕获到异常,真高兴')
#coding=utf-8
import time
try:
f = open('test.txt')
try:
while True:
content = f.readline()
if len(content) == 0:
break
time.sleep(2)
print(content)
except:
#如果在读取文件的过程中,产生了异常,那么就会捕获到
#比如 按下了 ctrl+c
pass
finally:
f.close()
print('关闭文件')
except:
print("没有这个文件")
异常的传递同java
抛出自定义异常
class ShortInputException(Exception):
'''自定义的异常类'''
def __init__(self, length, atleast):
#super().__init__()
self.length = length
self.atleast = atleast
def main():
try:
s = input('请输入 --> ')
if len(s) < 3:
# raise引发一个你定义的异常
raise ShortInputException(len(s), 3)
except ShortInputException as result:#x这个变量被绑定到了错误的实例
print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (result.length, result.atleast))
else:
print('没有异常发生.')
main()
模块
在Python中有一个概念叫做模块(module),这个和Java中的包很类似,模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块
import模块
#1
import module1,mudule2... #在调用模块中的函数时,必须这样引用:模块名.函数名
#2
from 模块名 import 函数名1,函数名2.... #通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同名称函数的时候,后面一次引入会覆盖前一次引入。
#3
from 模块名 import * #把一个模块的所有内容全都导入到当前的命名空间
#4
import time as tt #给time模块命名为tt,time这个名字不能再使用了
定位模块
当你导入一个模块,Python解析器对模块位置的搜索顺序是:
- 当前目录
- 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
- 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
- 模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
模块制作
每个Python文件都可以作为一个模块,模块的名字就是文件的名字。
例如
#test.py
def add(a,b):
return a+b
# 用来进行测试
ret = add(12,22)
print('int test.py file,,,,12+22=%d'%ret)
#main.py
import test #但是这样会有很大的问题,因为要先加载test模块,这个时候会先执行test模块中的类方法,也就是如上的测试代码, 即ret = add(12,22) print('int test.py file,,,,12+22=%d'%ret),而这些是根本不应该执行的,为此引入了__name__机制
result = test.add(11,22)
print(result)
改进
#test.py
# coding=utf-8
def add(a, b):
return a + b
print(__name__)
# 用来进行测试,只有执行python test.py的时候该方法才能执行,因为只有这个时候__name__才等于__main__
if __name__ == '__main__':
ret = add(12, 22)
print('int test.py file,,,,12+22=%d' % ret)
#main.py
import test # 在执行的时候,此时test.py 中的__name__变量等于`test`
result = test.add(3, 4)
print(result)
all变量
如果一个文件中有all变量,那么也就意味着这个变量中的元素,不会被from xxx import *时导入
__all__ = ['add', 'test1']
def add(a, b):
return a + b
def test1():
print('test1')
def test2():
print('test2')
将文件夹配置成模块
在文件夹下创建__init__.py
文件
在文件夹下面写入要导入的文件(.py)的文件名
例如
__all__ = ['test', 'msg']
- 包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为
__init__.py
文件,那么这个文件夹就称之为包
- 有效避免模块名称冲突问题,让应用组织结构更加清晰
-
__init__.py
控制着包的导入行为 - 在
__init__.py
文件中,定义一个__all__
变量,它控制着 from 包名 import *时导入的模块 - 可以通过
import Phone.Mobile.Analog
的方式导包
模块发布
新建setup.py
配置文件
from distutils.core import setup #导入发布工具包
setup(name="dongGe", version="1.0", description="dongGe's module", author="dongGe", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])
mymodule目录结构体如下:
.
├── setup.py
├── suba
│ ├── aa.py
│ ├── bb.py
│ └── __init__.py
└── subb
├── cc.py
├── dd.py
└── __init__.py
构建模块
python setup.py build
-- 会生成一个build
目录
生成发布压缩包
python setup.py sdist
打包后,生成最终发布压缩包dongGe-1.0.tar.gz
模块安装、使用
1.安装的方式
- 找到模块的压缩包
- 解压
- 进入文件夹
- 执行命令
python setup.py install
注意:
- 如果在install的时候,执行目录安装,可以使用
python setup.py install --prefix=安装路径
2.模块的引入
在程序中,使用from import 即可完成对安装的模块使用
from 模块名 import 模块名或者*
脚本技巧
传参:
import sys
print(sys.argv)
#rentianxin@rentianxin-Desk ~/D/P/HelloWord> python3 params.py a b 1
#['params.py', 'a', 'b', '1']