1.元组和列表
元组创建
a = 1,2,3
b = (1,2,3) #()可加可不加
c = (1,) # 仅包含一个元素也必须加上,
- 元组不可修改,列表可修改
元组: nums = (1,2,3,4)
列表: nums = [1,2,3,4]
常用列表方法
- append
- clear
- copy
a = [1,2,3]
b = a # 浅拷贝,b只是a的别名
b = a.copy() # 深拷贝
- count
# 计算元素出现了多少次
a = [1,3,4,2,1,2,1]
a.count(1) # 等于3
- extend 列表拼接,无须像"+"一样生成新的一个列表
a = [1,2,4]
b =[4,5,6]
a.extend(b)
- index 查找元素第一次出现的索引
a = [1,2,4]
a.index(1) #等于0
- insert 在指定位置插入数据
a = [1,2,3,4,5,6]
a.insert(3, "four")
# 等价于 a[3:3] = "four"
- pop 删除末尾元素并返回,与append函数配合可将列表作为栈使用
- remove 移除指定元素
- sort 对列表就地排序且不返回任何值!
# 如果想获得一个排序后的结果又不想更改原元组的顺序
a = [1,2,3,4]
# b = a.sort() # b为空
b = a.copy()
b.sort()
字符串
设置字符串的格式
1.类C版
format = "hello, %s. %s enough for you?"
values = ("world", "hot")
printstr= format % values
2.推荐使用字符串format方法
str = "{}, {} and {}".format("first", "second", "third")
# 也可以如下:,输出 to be or not to be
str = "{3} {0} {2} {1} {3} {0}".format("be", "not", "or", "to")
# 也可以
str = "{id} is {name}".format(id = 12, name = "zhu")
########
# 变量与替换字段同名,可以使用如下写法:
from math import e
f"Euler`s constant is roughtly {e}."
# 设置精度和宽度
"{num:.2f} and {name:10}".format(num = 1.23123, name = "zhujinde")
####
字符串方法
- find 查找子串,找到返回首字母索引,找不到则-1
- join 合并序列的元素,只能对字符串进行合并
num = ['1', '2', '3', '4']
seq = "+"
str = seq.join(num) # str = "1+2+3+4"
- lower 返回字符串的小写版本
- replace 子串替换
"this is a test".replace("is", "eez")
- split 根据给定字符进行字符串拆分
str = "1+2+3+4"
s = str.split('+') # s = ['1', '2', '3', '4']
字典
字典方法
- clear 原地删除所有字典项,返回none,原字典成为{}
d ={}
d["name"] = "zhu"
return_value = d.clear()
# 此时 d = {}, return_value = None
- copy 复制字典,但为浅复制,因为值本身是原件。深拷贝使用deepcopy。
x = {"id":12}
# 浅拷贝
y = x.copy()
# 深拷贝
z = deepcopy(x)
- fromkeys 创建一个新的字典,其中包含指定的键盘,且每个键对应的都是none
mydict = {}.fromkeys(["name", "age"])
# 上面多了个临时字典{},推荐直接使用以下方式:
mydict = dict.fromkeys(["name", "age"])
- get 相比mydict["name"]的直接访问方法,get在key不存在时不会抛出异常,而是会返回None,也可以指定默认错误返回值
mydict = {}.fromkeys(["name", "age"])
mydict["grade"] # 执行错误,异常
mydict.get("grade") # 返回none
mydict.get("grade", "N/A") # 返回 N/A
- items 返回一个包含所有字典项的列表,每个元素都为(key, value)形式,排序不定。返回值为一种名为 字典视图 的特殊类型
mydict = {}.fromkeys(["name", "age"])
print(mydict.items()) # 输出dict_items([('name', None), ('age', None)])
- keys 返回所有键值的字典视图
mydict = {}.fromkeys(["name", "age"])
print(mydict.keys())
#
- pop 获取指定key对应的值,并将其从字典中删除
- update 使用一个字典中的项来更新另一个字典。没有的k-v直接添加,相同的Key就更新
ori = {
"title" : "tx",
"url" : "www.qq.com"
}
newInfo = {"title" : "alibaba", "url" : "www.alibaba.com", "place" : "hangzhou"}
ori.update(newInfo)
print(ori) # 输出{'title': 'alibaba', 'url': 'www.alibaba.com', 'place': 'hangzhou'}
- values 返回值的字典视图
一些特殊函数
- exec 函数exec将字符串作为代码执行,无返回值。为避免所执行的字符串中的变量和外部的变量产生冲突,我们可以加入一个命名空间。
from math import sqrt
scope = {} # 命名空间
exec("sqrt = 1", scope) # sqrt属于命名空间scope,不会和外部的sqrt函数冲突
sqrt(4) # 输出2.0
## 可以以如下方式在命名空间中添加新的值
scope['x'] = 2
scope['y'] = 3
- eval 功能类似exec,但使用字符串返回执行的字符串的返回值
scope = {}
scope['x'] = 2
scope['y'] = 3
print(eval("x * y", scope)) # 输出6
- 不定长参数
*params:不会收集关键字参数,收集到的输入参数是一个元祖;
**params :会收集关键字参数,收集到的输入是一个字典;
def fun1(x, *y, z):
print(x, y, z)
# 如果*params不在最后一位,需要显示指定后续参数
fun1(1, 2, 3, 4, z =5)
#
def fun2(x, y, z = 3, *pospar, **keypar):
print(x, y, z)
print(pospar)
print(keypar)
fun2(1,2,3,4,5,6,7, foo = 1, bar = 2)
` 输出如下:
1 2 3
(4, 5, 6, 7)
{'foo': 1, 'bar': 2}
`
- map(func, seq) 对序列seq中的所有函数执行func
a = list(map(str, range(10))) # 与str(i) for i int range(10)等价
print(a) # list:将元组转换为数组。输出['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
- filter(func, seq) 过滤操作,返回一个列表,期中包含对func执行结果为真的所有结果
def func(x):
return x.isalnum()
seq = ["foo", "x31", "?12", "*^&*"]
a = list(filter(func, seq))
print(a) # 输出['foo', 'x31']
类
类似静态变量和成员变量
class test:
member = 0
def init(self):
test.member += 1 # 类似静态变量,member由所有类成员实例维护
# self.member += 1 # 修改的member只属于当前变量
def xprint(self):
print(self.member)
私有成员和方法
要让方法或属性成为私有的(不能从外部访问),只需让其名称以两个下划线打头即可。
class Secretive:
def __inaccessible(self):
print("Bet you can't see me ...")
def accessible(self):
print("The secret message is:")
self.__inaccessible()
现在从外部不能访问__inaccessible,但在类中(如accessible中)依然可以使用它。 虽然以两个下划线打头有点怪异,但这样的方法类似于其他语言中的标准私有方法。然而,幕后的处理手法并不标准:在类定义中,对所有以两个下划线打头的名称都进行转换,即在开头加上一个下划线和类名。
>>> Secretive._Secretive__inaccessible
<unbound method Secretive.__inaccessible>
只要知道这种幕后处理手法,就能从类外访问私有方法,然而不应这样做。
>>> s._Secretive__inaccessible()
Bet you can't see me ...
总之,你无法禁止别人访问对象的私有方法和属性,但这种名称修改方式发出了强烈的信号, 让他们不要这样做。
如果你不希望名称被修改,又想发出不要从外部修改属性或方法的信号,可用一个下划线打头。这虽然只是一种约定,但也有些作用。例如,from module import *不会导入以一个下划线打头的名称。
调用超类的构造函数
class Bird:
def __init__(self):
self.hungry = True def
eat(self):
if self.hungry:
print('Aaaah ...')
self.hungry = False
else:
print('No, thanks!')
class SongBird(Bird):
def __init__(self):
# Bird.__init__(self)
##或者使用函数super()
super().__init__()
self.sound = 'Squawk!'
def sing(self):
print(self.sound)
函数property
函数property使用起来很简单。如果你编写了一个类,如前一节的Rectangle类,只需再添加 一行代码。
class Rectangle:
def __init__ (self):
self.width = 0
self.height = 0
def set_size(self, size):
self.width, self.height = size
def get_size(self):
return self.width, self.height
size = property(get_size, set_size)
在这个新版的Rectangle中,通过调用函数property并将存取方法作为参数(获取方法在前, 设置方法在后)创建了一个特性,然后将名称size关联到这个特性。这样,你就能以同样的方式 对待width、height和size,而无需关心它们是如何实现的。
r = Rectangle()
r.width = 10
r.height = 5
>>> r.size
(10, 5)
>>> r.size = 150, 100
>>> r.width
150
如你所见,属性size依然受制于get_size和set_size执行的计算,但看起来就像普通属性一样。
实际上,调用函数property时,还可不指定参数、指定一个参数、指定三个参数或指定四 个参数。如果没有指定任何参数,创建的特性将既不可读也不可写。如果只指定一个参数(获取方法),创建的特性将是只读的。第三个参数是可选的,指定用于删除属性的方法(这个方 法不接受任何参数)。第四个参数也是可选的,指定一个文档字符串。这些参数分别名为fget、fset、fdel和doc。如果你要创建一个只可写且带文档字符串的特性,可使用它们作为关键字参数来实现。
本节虽然很短(旨在说明函数property很简单),却非常重要。这里要说明的是,对于新式类,应使用特性而不是存取方法。
深度探索继承
要确定一个类是否是另一个类的子类,可使用内置方法issubclass。
>>> issubclass(SPAMFilter, Filter)
True 11 >>> issubclass(Filter, SPAMFilter)
False
如果你有一个类,并想知道它的基类,可访问其特殊属性__bases__。
SPAMFilter.__bases__
(<class __main__.Filter at 0x171e40>,)
Filter.__bases__
(<class 'object'>,)
同样,要确定对象是否是特定类的实例,可使用isinstance。
s = SPAMFilter()
isinstance(s, SPAMFilter)
True
isinstance(s, Filter)
True
isinstance(s, str)
False
使用isinstance通常不是良好的做法,依赖多态在任何情况下都是更好的选择。一个
重要 的例外情况是使用抽象基类和模块abc时。
如你所见,s是SPAMFilter类的(直接)实例,但它也是Filter类的间接实例,因为SPAMFilter 是Filter的子类。换而言之,所有SPAMFilter对象都是Filter对象。从前一个示例可知,isinstance 也可用于类型,如字符串类型(str)。
如果你要获悉对象属于哪个类,可使用属性__class__。
s.__class__
<class __main__.SPAMFilter at 0x1707c0>
相关函数
callable(object) 判断对象是否是可调用的(如是否是函数或方法)
getattr(object,name[,default]) 获取属性的值,还可提供默认值
hasattr(object, name) 确定对象是否有指定的属性
isinstance(object, class) 确定对象是否是指定类的实例
issubclass(A, B) 确定A是否是B的子类
random.choice(sequence) 从一个非空序列中随机地选择一个元素
setattr(object, name, value) 将对象的指定属性设置为指定的值
type(object) 返回对象的类型
静态方法和类方法
讨论旧的特性实现方式之前,先来说说另外两种实现方式类似于新式特性的功能。静态方法 和类方法是这样创建的:将它们分别包装在staticmethod和classmethod类的对象中。静态方法的 定义中没有参数self,可直接通过类来调用。类方法的定义中包含类似于self的参数,通常被命 名为cls。对于类方法,也可通过对象直接调用,但参数cls将自动关联到类。下面是一个简单的 示例:
class MyClass:
def smeth():
print("this is a static method")
smeth = staticmethod(smeth)
def cmeth(cls):
print('This is a class method of', cls)
cmeth = classmethod(cmeth)
像这样手工包装和替换方法有点繁琐。在Python 2.4中,引入了一种名为装饰器的新语法, 可用于像这样包装方法。(实际上,装饰器可用于包装任何可调用的对象,并且可用于方法和函 数。)可指定一个或多个装饰器,为此可在方法(或函数)前面使用运算符@列出这些装饰器(指定了多个装饰器时,应用的顺序与列出的顺序相反)。
class MyClass:
@staticmethod
def smeth():
print('This is a static method')
@classmethod
def cmeth(cls):
print('This is a class method of', cls)
定义这些方法后,就可像下面这样使用它们(无需实例化类):
>>> MyClass.smeth()
This is a static method
>>> MyClass.cmeth()
This is a class method of <class '__main__.MyClass'>
异常
内置的异常类
Exception 几乎所有的异常类都是从它派生而来的
AttributeError 引用属性或给它赋值失败时引发
OSError 操作系统不能执行指定的任务(如打开文件)时引发,有多个子类
IndexError 使用序列中不存在的索引时引发,为LookupError的子类
KeyError 使用映射中不存在的键时引发,为LookupError的子类\
NameError 找不到名称(变量)时引发
SyntaxError 代码不正确时引发
TypeError 将内置操作或函数用于类型不正确的对象时引发
ValueError 其类型正确但包含的值不合适
ZeroDivisionError 在除法或求模运算的第二个参数为零时引发
向上传播异常
捕获异常后,如果要重新引发它(即继续向上传播),可调用raise且不提供任何参数
class MuffledCalculator:
muffled = False
def calc(self, expr):
try:
return eval(expr)
except ZeroDivisionError:
if self.muffled:
print('Division by zero is illegal')
else:
raise
万事大吉时
在有些情况下,在没有出现异常时执行一个代码块很有用。为此,可像条件语句和循环一样, 给try/except语句添加一个else子句。
try:
print('A simple task')
except:
print('What? Something went wrong?')
else:
print('Ah ... It went as planned.')
如果你运行这些代码,输出将如下:
A simple task\
Ah ... It went as planned.
通过使用else子句,可实现8.3.3节所说的循环。
while True:
try:
x = int(input('Enter the first number: '))
y = int(input('Enter the second number: '))
value = x / y
print('x / y is', value)
except:
print('Invalid input. Please try again.')
else:
break
在这里,仅当没有引发异常时,才会跳出循环(这是由else子句中的break语句实现的)。换 而言之,只要出现错误,程序就会要求用户提供新的输入。
生成器
生成器是一个相对较新的Python概念。由于历史原因,它也被称为简单生成器(simple generator)。生成器是一种使用普通函数语法定义的迭代器。
生成器创建起来与函数一样简单。你现在肯定厌烦了老套的斐波那契数列,所以下面换换口 味,创建一个将嵌套列表展开的函数。这个函数将一个类似于下面的列表作为参数:
nested = [[1, 2], [3, 4], [5]]
换而言之,这是一个列表的列表。函数应按顺序提供这些数字,下面是一种解决方案:
def flatten(nested):
for sublist in nested:
for element in sublist:
yield element
这个函数的大部分代码都很简单。它首先迭代所提供嵌套列表中的所有子列表,然后按顺序 迭代每个子列表的元素。倘若最后一行为print(element),这个函数将容易理解得多,不是吗?
在这里,你没有见过的是yield语句。包含yield语句的函数都被称为生成器。这可不仅仅是 名称上的差别,生成器的行为与普通函数截然不同。差别在于,生成器不是使用return返回一个 值,而是可以生成多个值,每次一个。每次使用yield生成一个值后,函数都将冻结,即在此停止执行,等待被重新唤醒。被重新唤醒后,函数将从停止的地方开始继续执行。
为使用所有的值,可对生成器进行迭代。
>>> nested = [[1, 2], [3, 4], [5]]
>>> for num in flatten(nested):
... print(num) ...
1 2 3 4 5
或
>>> list(flatten(nested))
[1, 2, 3, 4, 5]
从任意长度的可迭代对象中分解元素
def drop_first_last():
record = ('dave', '192312031', '777-23134', 'dava@example.com')
first, *middle, last = record
return middle
魔方方法
www.cnblogs.com/ningxinjie/… blog.csdn.net/qq_40196164…