python学习笔记
text = "我叫{0},今年{1}岁".format("cdh",23)
text = "我叫{0},今年{1}岁,真实姓名是{0}".format("cdh",23)
text = "我叫{n1},今年{1}岁,真实姓名是{0}".format(n1 = "cdh")
text = "我叫{0},今年{1}岁"
data1 = text.format("cdh",23)
data2 = text.format("ckj",23)
name = "cdh"
text = "我叫%s,今年23岁" %name
name = "cdh"
age = 23
text = "我叫%s,今年%d岁" %(name,age)
message = "%(name)s出货啦!" %{"name":"cdh"}
text = "%s,已经完成了90%%了" %"老板"
print(text)
2.3 f
到python3.6版本
text = f"我喜欢{'跑步'}"
action = "跑步"
text = f"我喜欢{action}"
name = "喵喵"
age = 5
text = f"我的猫叫{name},今年{age}岁"
可以传入表达式
text = f"我的猫叫喵喵,今年{5+1}岁"
#进制转换
text = f"我的猫今年{5}岁"
#转换为二进制
text2 = f"我的猫今年{5:#b}岁"
#八进制
text2 = f"我的猫今年{5:#o}岁"
#十六进制
text2 = f"我的猫今年{5:#x}岁"
3.1 运算符
成员运算,是否包含
in
not in
优先级:算数运算符>比较> not and or
4 Python中的编码
字符串(str) unicode编码
字节(byte) utf-8或gbk编码
text = "巧克力"
text2 = "巧克力".encode("utf-8")
text2 = "巧克力".encode("gbk")
5 Python中的进制
v1 = bin(25) #十进制转换为二进制 0b11001
v1 = oct(25) #十进制转换为八进制 0o27
v1 = hex(25) #十进制转换为十六进制 0x1c
int("0b11001",base = 2) #二进制转换为十进制
数据类型
python3中去除了long只剩下:int(整型),并且int长度不再限制
1.1 地板除
-
Py3:
v1 = 9/2 print(v1) #4.5 -
Py2:
v1 = 9/2 print(v1) #4from _future_ import division v1 = 9/2 print(v1) #4.5
字符串
#判断开头 结尾
str.startwith()
str.endwith()
#判断字符串是否为十进制整数
str.isdecimal()
#去除字符串两边的空格、换行符、制表符,得到一个新的字符串
str.strip()
str.lstrip()# 去除左边的空白
str.rstrip()# 去除右边的空白
# 去除字符串两边指定的内容
str.strip("something")
#字符串内容变大写 得到一个新的字符串
str.upper()
#字符串变小写
str.lower()
# 字符串内容替换
str.replace("old","new")
# 字符串切割,得到一个列表
data = "dd|root|dd@qq.com"
result = data.split('|') #['dd','root','dd@qq.com']
result2 = data.split('|',1) #['dd','root|dd@qq.com'] 数字控制切几个
result2 = data.rsplit('|',1) #['dd|root','dd@qq.com'] 从右边开始切
# 字符串拼接 形成一个字符串
data_list = ['cdh','like','dog']
v1 = "*".join(data_list) #用"*"拼接字符串 cdh*like*dog
# 字符串格式化见上面
# 字符串转换为字节类型
data = "cdh" # unicode,字符串类型
v1 = data.encode("utf-8") # utf-8,字节类型
a1 = v1.decode("utf-8") #cdh
# 字符串内容居中、居左、居右
v1 = "cdh"
data = v1.center(21,"*") # *********cdh*********
data = v1.ljust(21,"*") #居左 cdh******************
data = v1.rjust(21,"*") #居右 ******************cdh
# 填充0
str.zfill(num)
# 应用:处理二进制数据
data = "101"
v1 = data.zfill(8) # 00000101
#字符串长度
len(str)
#可以通过索引取值无法修改值
#获取字符串中的子序列 只能读取不能修改
str[num1:num2] #num1取 num2不取
str[num1:num2:num3] #num3步长
range(10) #[0,1,2,3,4,5,6,7,8,9]
range(1,10) #[1,2,3,4,5,6,7,8,9]
range(1,10,2) #[1,3,5,7,9]
range(10,1,-1) #[10,9,8,7,6,5,4,3,2]
字符串不可被修改
列表
列表(list)有序可变,可以存放多个不同类型的元素
不可变类型:字符串、布尔、整型
list.append("something") #添加元素
#批量追加
list.extend(list)
# 插入
list.insert(index,thing)
# 删除
list.remove(value)# 存在才能删,否则报错
list.pop(index)# 按照索引删除 可以将删除的值赋值给另一个变量
list.index(value)# 找值的索引位置 值需要存在
list.sort() #排序
list.sort(reverse = True) #从大到小排序
ord(char) #获取unicode值(十进制形式)
#列表可以相加、相乘
# in 关键字可以判断元素是否在列表中
if str in list:
...
len(list) #获取列表长度
del list[index] #删除元素
#切片
list[index1:index2] #前取后不取
list[index1:index2:step]
#实例:列表翻转
list = ["cdh","ckj","asd"]
new_list = list[::-1]
print(new_list)
list = ["cdh","ckj","asd"]
list.reverse() #列表独有的功能
print(list)
#for循环
list = ["cdh","ckj","asd"]
for item in list:
print(item)
list = ["cdh","ckj","asd"]
for index in range(len(list)):
item = list[index]
print(item)
# !!!循环中对数据进行删除,结果会出错
for item in list:
if ...:
list.remove(item)#错误!!!!!
#正确做法:倒着删除
for index in range(len(list)-1,-1,-1):
item = list[index]
if ...:
list.remove(item)
#列表中可以嵌套列表
元组
元组(tuple):有序、不可变的容器
#example
v1 = (11,22,33)
v2 = ("cdh","ckj")
v3 = (True,11,"cdh")
#建议:在元组的最后加一个",",表明这是一个元组
d1 = (1) #整型1
d2 = (1,) #元组(1,)
#与列表相似,元组可以相加、相乘、取长度、索引、切片、步长、for循环
#其他类型数据变元组 tuple(其他类型) 暂时只有str、list、set可以转换
name = "cdh"
data = tuple(name)
print(data) #输出("c","d","h")
name = ["cdh","ckj"]
data = tuple(name)
print(data) #输出("cdh","ckj")
#元组中可以嵌套元组
集合(set)
集合:无序、可变、不允许数据重复的容器
v1 = {11,22,33,"cdh"}
-
无序:无法通过索引取值
-
可变:可以添加或删除元素
-
不允许数据重复。
v1 = {11,22,33} v1.add(11) print(v1) #{11,22,33}
注意:定义空集合时,只能用v = set(),不能v = {} (这样是空字典)
v1 = [] #空列表
v11 = list()
v2 = () #空元组
v22 = tuple()
v3 = set() #空集合
v4 = {} #空字典
v44 = dict()
独有功能
1.添加元素
data = {"cdh","ckj"}
data.add("asd")
2.删除元素
data = {"cdh","ckj"}
data.discard("cdh")
3.交集
set1.intersection(set2)
set1 & set2
4.并集
s1.union(s2)
s1 | s2
5.差集
s1 - s2
s1.difference(s2) #s1中有s2中没有的值
公共功能
求长度、for循环
转换
set(其他类型) #可以用来去重!!!
集合中的元素必须是可哈希的!
目前可哈希的数据类型:int、bool、str、tuple,而list、set是不可哈希的
总结:集合中的元素只能是int、bool、str、tuple
None类型
相当于其他语言中的null,意味着这个值啥都不是或表示空
字典(dict)
字典是无序、键不重复且元素只能是键值对的可变容器
- 元素必须是键值对
- 键不重复,重复则会被覆盖
- 无序(python3.6+字典是有序的了,之前是无序的)
data = {"k1":1,"k2":2}
info = {
"age":12,
"status":True,
"name":"ckj",
"hobby":["游泳","阅读"]
}
键值的要求:
- 键:必须可哈希。目前为止,可哈希的 int/bool/str/tuple;不可哈希的 list/set/dict
- 值:任意类型
独有功能
1.获取值
info = {
"age":12,
"status":True,
"name":"ckj",
"hobby":["游泳","阅读"]
}
data = info.get("name")
print(data) #输出:ckj
data2 = info.get("email")
print(data2) #键不存在返回None
data3 = info.get("email",123)
print(data3) #键存在,返回对应的值,键不存在,返回123
2.所有的键
info = {
"age":12,
"status":True,
"name":"ckj",
"hobby":["游泳","阅读"]
}
data = info.keys()
print(data) #dict_keys(['age','status','name','hobby'])
3.所以的值
info = {
"age":12,
"status":True,
"name":"ckj",
"hobby":["游泳","阅读"]
}
data = info.values()
print(data) #dict_keys([12,True,'ckj',['游泳','阅读']])
4.所有的键值
info = {
"age":12,
"status":True,
"name":"ckj",
"hobby":["游泳","阅读"]
}
data = info.items()
print(data) #dict_keys([('age',12),('status',True),('name','ckj'),('hobby',['游泳','阅读'])])
for key,value in info.items():
print(key,value) #可以将键值从元组中拆分出来
#设置值
data.setdefault("key",value) #不存在则添加,存在就不设置了
#更新键值对
data.update(dict) #传入的是一个字典,不存在则添加,存在则修改
#移除键值对
data = dict.pop("key") #data获取到移除的键对应的值
#按顺序移除(后进先出)
data = dict.popitem() #data是一个元组包含键值
#3.6之后移除最后一个
#3.6之前随机移除
公共功能
求并集(python3.9 后加入)
dict3 = dict1 | dict2
求长度
len(dict)
是否包含
if "key" in dict: #判断键是否在字典里
...
if "key" in dict.keys():
...
if "value" in dict.values():
...
if ("key","value") in dict.items():
...
索引(键)
dict["key"]
#根据键可以修改、添加、删除键值对
dict["key"] = "value" #没有则添加,有则修改
del dict["key"] #删除键值对 不存在时报错
转换(对转换的类型格式有要求)
字典会对键进行哈希处理!
浮点型(float)
浮点型转换为整型,小数点之后的内容舍弃
#保留小数点后N位,会完成四舍五入
v1 = 3.1415926
result = round(v1,3)
print(result) #3.142
若需要精确的小数运算
import decimal
v1 = decimal.Decimal("0.1")
v2 = decimal.Decimal("0.2")
v3 = v1 + v2
print(v3) #0.3
is 和 == 的区别
- == 比较两个值是否相等
- is 表示内存地址是否一致
位运算
-
&,与
-
|,或
-
^,异或
-
~,取反
-
<<,左移
-
>> #右移
模块
导入路径
会去指定路径下查找导入的模块,现在当前目录下找,之后去python内部路径下找
导入模块时添加路径
import sys
sys.path.append('pathA') # sys.path返回一个列表
import xxxxx # 导入的路径下的py文件
import os
os.path.abspath(__file__) #当前文件所在绝对路径
os.path.dirname(pathA) #pathA的上一层路径
pycharm会自动把项目目录加入到 sys.path!
导入方式
导入一个模块
import xxx #xxx.fun()
import xxx.xxx # 使用模块下函数时需写出完整路径 xxx.xxx.fun()
import xxx.xxx as aa # aa.fun()
导入成员
from xxx import fun #fun()
from xxx import xx #xx.fun()
- import:导入项目根目录的包或模块
- from:导入嵌套的包或模块
导入同名的模块或成员时取别名!
-
执行一个py文件时
__name__ = "__main__" -
导入一个py文件时
__name__ = "模块名"
python 中主文件可以通过如下代码识别
if __name__ = '__main__': #也可用来进行模块测试
...
第三方模块
pip默认安装最新版本,如果想指定安装的版本
pip3.9 install 模块名称==版本
#例如
pip3.9 install django==2.2
从国内的源下载模块
-
一次性使用
pip3.9 install 模块名称 -i https://pypi.douban.com/simple/ -
永久使用
配置
# 在终端执行如下命令 pip3.9 config set global.index-url https://pypi.douban.com/simple/ # 也可打开文件直接修改源 User/name/.config/pip/pip.conf
其他源
阿里云 http://mirrors.aliyun.com/pypi/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
函数
默认参数
def func(a1, a2, a3 = 10):
print(a1 + a2 + a3)
#位置传参
func(4,12)
func(4,12,33)
#关键字传参(位置和关键混合时,关键字传参要在后面)
func(12,9,a3=90)
func(12,a2=3,a3=90)
动态参数
-
def func(*args): print(args) #args为元组类型 #只能按位置传参 func(22) func(22,33) func()
def func(**kwargs):
print(kwargs) #字典类型
#只能按关键字传参
func(n1 = "cdh") #{"n1":"cdh"}
func(n1 = "cdh",n2 = "ckj") #{"n1":"cdh","n2":"ckj"}
-
,*
def func(*args,**kwargs): print(args,kwargs) #根据传值的方式自动将数据放进元组或字典 func(22,12) func(22,n1 = "cdh")#**必须放在*后面 #参数和动态参数混合时,动态参数放在后面
查看某个值在内存中的地址
v1 = "cdh"
addr = id(v1)
print(addr)
python函数执行传参时,传递的是内存地址!!!
好处:
- 节省内存
- 对可变类型进行修改时,所有地方都会修改。可变类型:字典、列表、集合
在python中如果想只传递值,可以先拷贝一份
import copy
new_data = copy.deepcopy(data)
func(new_data)
python中函数的返回值是内存地址!!!
函数中的默认参数
python在创建函数(未执行)时,如果发现函数存在默认参数,则在函数内部会创建一块区域并维护这个默认值
- 执行函数未传值时,则让a2指向函数维护的那个值的地址
- 执行函数传值时,则让a2指向新传入的值的地址
当默认参数的值是可变类型(list/dict/set)并且在函数内部会修改这一值时,会出现问题!
#在函数内存中维护一块区域存储 100010001
def func(a1,a2=[1,2]):
a2.append(666)
print(a1,a2)
#a1 = 100
#a2 -> 100010001
func(100) # 100 [1,2,666]
#a1 = 200
#a2 -> 100010001
func(200) # 200 [1,2,666,666]
#a1 = 99
#a2 -> 111111101
func(99,[77,88]) # 99 [77,88,666]
#a1 = 300
#a2 -> 100010001
func(300) # 300 [1,2,666,666,666]
在定义函数时可以用*和** ,在执行函数时,也可以使用
-
形参固定,实参用*和**
def func(a1,a2): print(a1,a2) func(11,22) func(a1=1,a2=2) func(*[11,22]) func(**{"a1":11,"a2":22}) -
形参用*和**,实参也用
def func(*args,**kwargs): print(args,kwargs) func(11,22) func(11,22,name="cdh",age=18) #小坑, ([11,22,33],{"k1":1,"k2":2}),{} func([11,22,33],{"k1":1,"k2":2}) #args=(11,22,33),kwargs={"k1":1,"k2":2} func(*[11,22,33],**{"k1":1,"k2":2}) #注意:按这种方式传参,数据会拷贝一份
所以,在使用format字符串格式化时,可以这样:
v1 = "我是{},年龄:{}".format("cdh",18)
v2 = "我是{name},年龄{age}".format(name="cdh",age=18)
v1 = "我是{},年龄:{}".format(*["cdh",18])
v2 = "我是{name},年龄{age}".format(**{"name":"cdh","age":18})
函数名其实就是一个变量,可以作为列表或字典中的元素
def func():
return 123
data_list = ["cdh","func",func,func()]
print(data_list[0]) #字符串"cdh"
print(data_list[1]) #字符串"func"
print(data_list[2]) #函数func
print(data_list[3]) #执行函数,获得返回值,整数123
res = data_list[2]()
print(res) #执行函数,输出返回值
#注意:函数可以被哈希,所以函数名可以作为集合的元素、字典的键
使用场景:
def send_message(phone,content):
"""发送消息"""
pass
def send_image(img_path,content):
"""发送图片"""
pass
def send_emoji(emoji):
"""发送表情"""
pass
def send_file(path):
"""发送文件"""
pass
function_dict = {
"1":[send_message, ['18861524789','hello!']],
"2":[send_image, ['xxx/xxx/xxx.png','content']],
"3":[send_emoji, ["some_emoji"]],
"4":[send_file, ['xx.zip']]
}
print("欢迎使用xx系统")
print("请选择:1.发送消息;2.发送图片;3.发送表情;4.发送文字")
choice = input("请输入选择的序号")
item = function_dict(choice) #如果没有会返回None
if not item:
print("输入错误!")
else:
#执行函数
func = item[0]
param_list = item[1]
func(*param_list)
使用场景2
def send_msg(mobile, content):
"""发送短信"""
pass
def send_email(to_email, subject, content):
"""发送邮件"""
pass
def send_wechat(user_id, content):
"""发送微信"""
pass
func_list = [
{"name": send_msg, "params": {'mobile':"18852462589","content":"你有新消息"}},
{"name": send_email, "params": {'to_email':"1845236589@qq.com","subject":"你有新消息","content":"你好"}},
{"name": send_wechat, "params": {'user_id':"12","content":"你有新消息"}}
]
for item in func_list:
func = item['name']
param_dict = item['params']
func(**param_dict)
在局部可以读取全局变量或修改全局变量的内部元素(可变类型),但无法对全局变量重新赋值
若要在局部修改全局的值,可以使用global关键字
COUNTRY = "China" #全局变量名尽量用大写
def upload():
global COUNTRY
COUNTRY = "中华人民共和国"
函数如果返回两个值,用逗号","分割,那么返回的是一个元组!
函数嵌套:可以防止函数重名
装饰器
-
实现原理:基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时在内层函数中执行闭包中的原函数。
-
实现效果:可以在不改变原函数内部代码和调用方式的前提下,实现函数执行和执行扩展功能
-
适用场景:多个函数系统统一在执行前后自定义一些功能
-
装饰器示例
import functools def outer(origin): @functools.wraps(func) # inner.__name__ = func.__name__ inner.__doc__ = func.__doc__ def inner(*args, **kwargs): #执行前 res = origin(*args, **kwargs)#调用原来的unc函数 #执行后 return res return inner @outer def func(): pass func()
python中@的用法
#在某个函数上方使用:
@函数名
def xxx():
pass
#python 内部会自动执行 函数名(xxx),执行完之后再将结果赋值给xxx
#相当于执行了
#xxx = 函数名(xxx) 函数名所指代的函数需在之前申明!!
匿名函数
基于Lambda定义的函数,格式为:lambda 参数:函数体
-
参数,支持任意参数
lambda x: 函数体 lambda x1,x2: 函数体 lambda *args, **kwargs: 函数体 -
函数体,只支持单行的代码
lambda x:x+100 -
返回值,默认将函数体单行代码执行的结果返回给函数的执行者
func = lambda x: x+100 v1 = func(10) print(v1) #110
三元运算
结果 = 条件成立时 if 条件 else 不成立
生成器
记录在函数中的执行位置,下次执行next时,会从上一次的位置基础上再继续向下执行
当函数中有yield时,这个函数就是生成器函数
执行生成器函数时,会返回一个生成器对象
注意:执行生成器函数时,函数内部代码不会执行!!
def func():
print(123)
yield 123
v1 = func()#函数体默认不会执行,返回一个生成器对象
#next里面放生成器对象,进入生成器函数并执行其中的代码,执行到yield为止
next(v1)
#n1 = next(v1) n1接收yield的返回值
推导式
用一行代码创建list、dict、tuple、set的同时初始化一些值
-
列表
num_list = [i for i in range(10)] num_list = [[i,i] for i in range(10)] num_list = [[i,i] for i in range(10) if i > 6] v = [lambda :x for x in range(10)] #列表中存放10个函数 -
集合
num_set = {i for i in range(10)} num_set = {(i,i,i) for i in range(10)} num_set = {(i,i,i) for i in range(10) if i > 3} -
字典
num_dict = {i:i for i in range(10)} num_dict = {i:(i,11) for i in range(10)} num_dict = {i:(i,11) for i in range(10) if i > 7} -
元组,不同于其他类型。
#不会立即执行内部循环去生成数据,而是得到一个生成器。 data = (i for i in range(10)) print(data) for item in data: print(item)
生成器函数实现斐波那锲数列
def fib(max_count):
first = 1
second = 0 #前两个值的设置是关键!!!!
count = 0
while count < max_count:
next_value = first + second
first = second
second = next_value
yield next_value
count += 1
limit_count = imput("输入要生成的斐波那锲数列的个数")
limit_count = int(limit_count)
fib_generator = fib(limit_count)
for num in fib_generator:
print(num)
正则表达式
1.字符相关
-
cdh 匹配文本中的cdh
import re text = "..." data_list = re.findall("cdh",text) -
[abc] 匹配a或b或c字符
data_list = re.findall("[abc]",text) data_list = re.findall("q[abc]",text) #qa、qb、qc -
[^abc]匹配除了abc以外的其他字符
-
[a-z]匹配a-z的任意字符([0-9]也可以)
-
. 代指处换行符以外的任意字符
data_list = re.findall("r.o",text) #rao、roo,.只能指代一个字符 data_list = re.findall("r.+o",text) #贪婪匹配,中间可以有任意个字符,获得最长的符合要求的字符 data_list = re.findall("r.+?o",text) #非贪婪匹配,获得最短的符合要求的字符 -
\w 指代字母或数字或下划线(汉字)
-
\d 代指数字
-
\s 代指任意的空白符,包括空格、制表符等
2.数量相关
- *重复0次或更多次
- +重复1次或更多次
- ?重复0次或1次
- {n}重复n次
- {n,}重复n次或更多次
- {n,m}重复n到m次
3.括号(分组)
- 提取数据区域
- 获取指定区域+条件
要求用户的内容必须是指定的内容开头和结尾
- ^开始
- $结束
特殊字符匹配前用\转义
面向对象
初识面向对象
通过面向对象实现某个功能时,需要两步:
- 定义类,在类中定义方法,在方法中实现具体功能
- 实例化类的一个对象,通过对象去调用并执行方法
class Message:
def send_email(self, email, content):
data = "给{}发邮件,内容是{}".format(email,content)
print(data)
msg_object = Message() #实例化一个对象
msg_object.send_email("1836581045@qq.com","注册成功")
注意:1.类名首字母大写&驼峰式命名;2.py3之后默认类都继承object;3.在类中编写的函数称为方法;4.每个方法第一个参数为self
对象和self
每个类中都可以定义一个特殊的:__init__初始化方法,在实例化创建对象时自动执行
class Message:
def __init__(self, content):
self.data = content
def send_email(self, email):
data = "给{}发邮件,内容是{}".format(email,self.data)
print(data)
#对象 = 类名() #自动执行类中的 __init__方法
#self指代创建的那个对象,self.data即在对象中创建一个data变量
msg_object = Message("注册成功") #实例化一个对象
msg_object.send_email("1836581045@qq.com")
常见成员
- 实例变量,属于对象,只能通过对象调用
- 绑定方法,属于类,通过对象调用或通过类调用
class Person:
def __init__(self, name, age):
#实例变量
self.name = name
self.age = age
#绑定方法
def show(self):
msg = "我叫{},今年{}岁。".format(self.name, self.age)
print(msg)
继承
class Base:
def func(self):
print("Base.func")
class Son(Base):
def show(self):
print("Son.show")
s1 = Son()
s1.show()
s1.func() #优先在自己的类中找,自己没有才去父类
b1 = Base()
b1.func()
python支持多继承
class TCPServer:
def f1(self):
print("TCPServer")
class ThreadingMixIn:
def f1(self):
print("ThreadingMixIn")
class ThreadindTCPServer(ThreadingMixIn, TCPServer):
def run(self):
print("before")
self.f1()
print("after")
obj = ThreadingTCPServer()
obj.run()
>>> before
>>> ThreadingMixIn #优先去第一个继承的类中找f1
>>> after
变量
- 实例变量:属于对象,每个对象各自维护自己的数据
- 类变量:属于类,可以被所有对象共享,一帮用于给对象提供公共数据
class Person():
country = "中国"
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
message = "{}-{}-{}".format(Person.country, self.name, self.age)
#message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
print(Person.country) #中国
p1 = Person("cdh", 18)
print(p1.name)
print(p1.age)
print(p1.country) #中国
p1.show() #中国-cdh-18
p1.name = "ckj" #在对象p1中将name重置
p1.num = 12 #在对象p1中新增变量 num = 19
p1.country = "China" #在对象p1中新增变量 country = "China"
print(p1.country) #China
print(Person.country) #中国
方法
- 绑定方法:默认有一个self参数,由对象进行调用(此时self就等于调用方法的这个对象)【对象和类均可调用】
- 类方法:默认有一个cls参数,用类或对象都可以调用(此时cls就等于调用方法的这个类)【对象和类均可调用】
- 静态方法:无默认参数,用类和对象都可以调用
class Foo(object):
def __init__(self, name):
self.name = name
def f1(self):
print("绑定方法", self.name)
@classmethod
def f2(cls):
print("类方法", cls)
@staticmethod
def f3():
print("静态方法")
#绑定方法
obj = Foo("cdh")
obj.f1()
#类方法
Foo.f2() #cls就是当前调用这一方法的类
obj.f2() #cls就是当前调用这个方法的对象的类
#静态方法
Foo.f3()
obj.f3()
属性
由绑定方法+特殊装饰器组合创造出来,在调用方法时可以不加括号,例如:
class Foo(object):
def __init__(self, name):
self.name = name
def f1(self):
return 123
@property
def f2(self):
return 123
obj = Foo("cdh")
v1 = obj.f1()
print(v1)
v2 = obj.f2
print(v2)
成员修饰符
- 公有,在任何地方都可以调用这个成员
- 私有,只有在类的内部才可以调用该成员(成员是以两个下划线开头,则表示该成员为私有,方法和属性前也可以加双下划线变为私有),父类中私有成员,子类无法继承
class Foo(object):
def __init__(self, name, age):
self.__name = name
self.age = age
def get_data(self):
return self.__name
def get_age(self):
return self.age
obj = Foo("cdh", 18)
obj.age
# obj.__name #无法访问
obj.get_data()
特殊成员
在python中存在一些特殊的方法,这些方法都是__方法__格式,均有特殊含义
-
__init__,初始化方法class Foo(object): def __init__(self, name): self.name = name obj = Foo("cdh") -
__new__,构造方法,在init方法前执行class Foo(object): def __init__(self, name): print("第二步,初始化对象,在空对象中创建数据") self.name = name def __new__(cls, *args, **kwargs): print("第一步,先创建空对象并返回") return object.__new__(cls) obj = Foo("cdh") -
__call__class Foo(object): def __call__(self, *args, **kwargs): print("执行call方法") obj = Foo() obj() #执行call方法 -
__str__class Foo(object): def __str__(self): return "something" obj = Foo() data = str(obj) print(data) #something -
__dict__class Foo(object): def __init__(self, name, age): self.name = name self.age = age obj = Foo("cdh", 18) print(obj.__dict__) #{"name":"cdh", "age":18} -
__getitem__,__setitem__,__delitem__#可以像列表一样操作类中的成员变量 -
__enter__,__exit__#上下文管理 -
__add__#让两个对象可以相加 -
__iter__迭代器
# 迭代器类型的定义: 1. 类中定义了 __iter__ 和 __next__两个方法 2. __iter__ 方法需要返回对象本身,即:self 3. __next__ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常 #创建迭代器类型 class IT(object): def __init__(self): self.counter = 0 def __iter__(self): return self def __next__(self): self.counter += 1 if self.counter == 3: raise StopIteration() return self.counter #根据类实例化创建一个迭代器对象: obj = IT() #V1 = obj.__next__() #V1 = obj.__next__() #V1 = obj.__next__() #抛出异常 v1 = next(obj) #obj.__next__() print(v1) v2 = next(obj) print(v1) v3 = next(obj) print(v1) obj2 = IT() for item in obj2: #首先会执行迭代器对象的__iter__方法并获取返回值,然后一直执行next(对象) print(item)

浙公网安备 33010602011771号