Python基本数据类型

运算符

算数运算:

  • 不同的数据类型几乎不能做算数运算,比如print("a"+123),会报错,但是有一个例外,str类型和int类型可以相乘print("a"*3),结果是str文本的倍数,即aaa

  • 除法得到的结果是浮点型而不是整型(这点不同于java语言,java语言的结果是整型),要想得到整型,可以用//运算符

比较运算:

赋值运算:

逻辑运算:

成员运算:

基本数据类型

整型(int)

n =123
n2 = 123
print(id(n))
print(id(n2))

上述id()方法用来查看内存地址,输出结果也是相同的,这是因为python内部机制优化,n和n2指向的是一同一块内存。
定义整型类型的方法有如下3种:

n =123
n = int(123)
n = int.__int__(123)

实际上内部调用方式也是这样的。Python的整数没有大小限制,而某些语言的整数根据其存储长度是有大小限制的,例如Java对32位整数的范围限制在-2147483648-2147483647。

布尔值

布尔值和布尔代数的表示完全一致,一个布尔值只有TrueFalse两种值,要么是True,要么是False,在Python中,可以直接用True、False表示布尔值(请注意大小写),也可以通过布尔运算计算出来:

>>> True
True
>>> False
False
>>> 3 > 2
True
>>> 3 > 5
False

字符串(str)

在最新的Python 3版本中,字符串是以Unicode编码的,也就是说,Python的字符串支持多语言,例如:

>>> print('包含中文的str')
包含中文的str

对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符:

>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'    

字符串的定义方式有如下几种:

test = "中国"
test = str("中国")
# 无参,创建空字符串
# 一个参数,普通字符串
# 两个参数,str(字节,编码)    

字符串和字节可以互转,但是要注意编码的一致,例如:

content = str(bytes("中国", encoding="utf-8"), encoding="utf-8")
print(content)

字符串是可以遍历的,3.x以上版本默认字符形式输出,我们可以通过bytes()方法转为字节,例如:

test = "中国"
for item in test:
    # 默认16进制输出
    print(item, bytes(item, encoding='gbk'))
    # for循环后以十进制输出
    for b in bytes(item, encoding='gbk'):
        print(b)

输出结果如下:

中 b'\xd6\xd0'
214
208
国 b'\xb9\xfa'
185
250

Python对bytes类型的数据用带b前缀的单引号或双引号表示,一个汉字,(utf-8编码)三个字节,(GBK)两个字节表示 ,\x代表16进制。

字符串格式化

我们经常会输出类似’亲爱的xxx你好!你xx月的话费是xx,余额是xx’之类的字符串,而xxx的内容都是根据变量变化的,所以,需要一种简便的格式化字符串的方式。在Python中,采用的格式化方式和C语言是一致的,用%实现。常见的点位符有:

其中,格式化整数和浮点数还可以指定是否补0和整数与小数的位数,举例如下:

print("小明是一个%s人" % "好")
print("小明考了%.1f分,这有%d个苹果,只有%s吃" % (99.8, 18, "小明"))
print('亲爱的%s你好!你%02d月的话费是%.2f,余额是%.2f' % ("小明", 6, 30.34, 105.33))
print('growth rate: %d %%' % 7)

输出结果如下:

小明是一个好人
小明考了99.8分,这有18个苹果,只有小明吃
亲爱的小明你好!你06月的话费是30.34,余额是105.33
growth rate: 7 %

%运算符就是用来格式化字符串的。在字符串内部,%s表示用字符串替换,%d表示用整数替换,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略。有些时候,字符串里面的%是一个普通字符怎么办?这个时候就需要转义,用%%来表示一个%:

字符串常用方法

content = 'good'
test = "小黑 is {0} ,小白 is {1}"
num = "一"
name = ["fanda", "fdf", "ed", "23ds", "9jss"]

# 首字母变大写
print(content.capitalize()) 

# 字符串内容居中,至少传一个 参数(总长度),第二个参数是需要     填充的内容,默认是""
print(content.center(10,"*"))

# 从0位开始,判断字符串出现的次数,可以传入开始和结束索引位
print(content.count("o"))
print(content.count("o", 2))

# 判断什么后缀结尾,可以选定范围来判断,下述是大于等于1,小于3的范围 ,索引从0开始
print(content.endswith("d",1, 3))

# 索引从0开始,如果有匹配的,后面不继续找,找到就返回索引位置,没找到就返回-1
print(content.find("d"))

# 字符串格式化
print(test.format("good", "well"))

print("是否是字母或数字", num.isalnum())

print("是否是字母或中文", num.isalpha())

# 判断的是Unicode数字,byte数字(单字节),全角数字(双字节),罗马数字
print("是否是数字", num.isdigit())

# 判断的是Unicode数字,全角数字(双字节),罗马数字,汉字数字
print("是否是数字", num.isnumeric())

# 用什么字符串来连接,传入可迭代对象
print("_".join(name))

# 去除左侧空格
print(content.lstrip())

# 去除右侧空格
print(content.rstrip())

# 去除两侧空格
print(content.strip())

# 分割,分割的字符串是一部分,之前的是一部分,后面的是一部分,结果是元组
print(content.partition("o"))

# 替换,用新的字符替换旧的,最后的数量参数,是可以替换的个数,超过的部分,就算匹配了也不替换,不传数量,默认替换所有
print(content.replace("o", "e",1))

# 分割,分割的字符串会消失,返回的是个列表,加数量参数后,超过分割字符串数量不再分割
content = "fnadafanda"
print(content.split("a", 1))
print(content.split("a"))

# 大写变小写,小写变成大写
content = "Fanda"
print(content.swapcase())

content = "fanda is good fanda fanda fanda"
# 变成标题,每个单词的首字母会大写
print(content.title())

# 全部变成大写
print(content.upper())

输出结果:

Good
***good***
o出现的次数= 2
o出现的次数= 1
False
3
小黑 is good ,小白 is well
是否是字母或数字 True
是否是字母或中文 True
是否是数字 False
是否是数字 True
fanda_fdf_ed_23ds_9jss
('g', 'o', 'od')
geod
['fn', 'dafanda']
['fn', 'd', 'f', 'nd', '']
fANDA
Fanda Is Good Fanda Fanda Fanda
FANDA IS GOOD FANDA FANDA FANDA

高级功能

索引,从0开始,可以通过索引来获取字符串中的字符,例如:

content = 'good'
print(content[0])

切片,用来批量获取内容,例如:

# >=0 ,<4,即0,1,2,3
print(content[0:4])

遍历,用来获取每个元素,例如:

for item in content:
    print(item)

列表(list)

list是一种有序的集合,list()方法传可迭代对象,内部将循环每一个元素,当做列表的元素,可迭代对象可以是字符串,元组或字典。

content1 = "小明"
content2 = ("fanda", "dfdf", "sd")
content3 = {"key1": "fanda", "key2": "hehe"}

print(list(content1))
print(list(content2))
print(list(content3))
#拿字典的值做为元素,默认拿的是字典的key
print(list(content3.values()))

输出结果:

['小', '明']
['fanda', 'dfdf', 'sd']
['key1', 'key2']
['fanda', 'hehe']

列表也可以用索引和切片功能,索引-1代表最后一个元素,-2代表倒数第二个元素,以此类推,例如:

classlist = ["fanda", "fanda", "sd", "kou", "good"]
print(len(classlist))
print(classlist[0])
print(classlist[:2])
print(classlist[-3:])
print(classlist[-1])

输出结果:

5
fanda
['fanda', 'fanda']
['sd', 'kou', 'good']
good

列表常用方法

classlist = ["fanda","kou", "good"]

# 追加元素到末尾
classlist.append("ewr")

# 追加可迭代对象,相当于批量追加
classlist.extend("good")

# 在相应位置插入数据
print(classlist.insert(1, "hehe"))

# 移除最后一个元素,并返回最后的元素,加参数则表示移除对应索引的元素,索引是从0开始的
last =classlist.pop()
index =classlist.pop(1)
print("pop的元素=", last)
print("pop的元素=", index)

# 移除对应的元素,只移除找到的第一个元素,其他重复的元素不管,没有返回参数,即返回None
classlist.remove("fanda")

# 用关键字的方式移除元素,可以通过切片批量删除
del classlist[1:3]

# 反转元素
classlist.reverse()

# 查询对应元素的索引
print(classlist.index('kou'))

# 遍历元素
for item in classlist:
    print(item)

# enumerate 方法可以给可迭代对象增加索引,下述方法就能给出列表每个元素加索引了,默认索引从0开始,可以指定开始的索引,如果不用这方法,只能自己算了
for k, v in enumerate(classlist):
    print(k, v)

print(classlist)

输出结果:

['fanda', 'kou', 'good', 'ewr']
['fanda', 'kou', 'good', 'ewr', 'g', 'o', 'o', 'd']
['fanda', 'kou', 'good', 'ewr', 'g', 'o', 'o', 'd', 123, 7, 3]
['fanda', 'hehe', 'kou', 'good', 'ewr', 'g', 'o', 'o', 'd', 123, 7, 3]
pop的元素= 3
pop的元素= hehe
['kou', 'g', 'o', 'o', 'd', 123, 7]
[7, 123, 'd', 'o', 'o', 'g', 'kou']
kou的索引= 6
0 7
1 123
2 d
3 o
4 o
5 g
6 kou

元组(tuple)

另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改。

classmates = ('Michael', 'Bob', 'Tracy')

现在,classmates这个tuple不能变了,它也没有append()insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用classmates[0]classmates[-1],但不能赋值成另外的元素。

如果要定义一个空的tuple,可以写成(),比如 t = (),但是,要定义一个只有1个元素的tuple ,如果这么定义t = (1),定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义,即要这样定义t = (1,)

tuple里面的元素可以是列表或元组,当元素是列表或元组时,列表和元组是可以修改的,比如:

t = (11, 22, ["fanda", {"k1": "v1"}])
t[2][1]["k1"] = "v2"
t[2][1]["k2"] = "v3"
t[2][0] = "v3"
print(t)

输出结果:

(11, 22, ['v3', {'k1': 'v2', 'k2': 'v3'}])

表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’11’,就不能改成指向’12’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!比如:

t[2] = [1, 2, 3]

上述代码就会报错,不能重新指向集合[1,2,3]。

理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。元组也有索引的,也可以遍历和切片,是可迭代对象,其功能与列表类似。

字典(dict)

dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,,键必须是不可变对象,在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key 。dict内部存放的顺序和key放入的顺序是没有关系的,没有切片,具有极快的查找速度。
字典也有索引,索引就是对应的key,通过key可以获取值,比如:

user_info = {0: "fanda", "age": 18, "gender": "man"}
# 索引
 print(user_info["age"])

如果直接遍历字典,输出的也是key,比如:

# 输出的是所有的key,相当于user_info.keys()
 for item in user_info:
     print(item)

输出结果:

0
age
gender

如果想输出字典的值,可以这样:

for item in user_info.values():
    print(item)

输出结果:

fanda
18
man

如果想要获取所有的键值对,可以这样:

for item in user_info.items():
    print(item)

输出结果:

(0, 'fanda')
('age', 18)
('gender', 'man')

每个元素以元组的形式表示

字典常用方法

# 清空所有内容
user_info.clear()

#遍历直接拿出所有的key,value
for k, v in user_info.items():
    print(k, v)

输出结果:

0 fanda
age 18
gender man

其他方法:

# 这种方式取值,若不存在,返回None,也可以返回指定的值,如果用索引的方式会报错
print(user_info.get(1, "234"))

# 移除了第一个键值对 
print(user_info.pop(0))

# 用关键字的方式移除元素,移除了key为"age"的键值对
del user_info["age"]
print(user_info)

# 3.x 版本没有了haskey方法,但是我们可以用in方式来判断
print("age" in user_info.keys())

列表和字典也可以相互转换,但是需要通过enumerate()方法增加索引列,默认索引从0开始,比如:

content = ["fanda", "fa", "da"]
print(dict(enumerate(content, 10)))

输出结果:

{10: 'fanda', 11: 'fa', 12: 'da'}

这里说一个特殊的方法,其源码如下:

@staticmethod  # known case
def fromkeys(*args, **kwargs):  # real signature     unknown
    """ Returns a new dict with keys from iterable and values equal to value. """
     pass

@staticmethod,有这个注释时,可以通过类来直接调用,相当于java的静态方法,比如:

content = dict.fromkeys(["key1", "key2", "key3"], [])
# 通过这种方式改变列表数据的时候,所有的数据都会改变
content["key1"].append("fanda")
print(content)

输出结果:

{'key1': ['fanda'], 'key2': ['fanda'], 'key3': ['fanda']}

set集合

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key,例如:

s = set([1, 1, 2, 3])
s = {1, 1, 2, 3}
print(s)

输出结果:

{1, 2, 3}

上述代码有两种创建set的方法,从结果可以知道自动过滤重复的key。注意显示的顺序也不表示set是有序的。

通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:

s.add(5)
s.add(6)
s.add(6)

输出结果:

{1, 2, 3, 5, 6}

通过remove(key)方法可以删除元素:

# 找不到会报错
s.remove(6)

# 找不到不会报错
s.discard(6)

# 找不到会报错,这个方法有返回值
s.pop(6)
# 不一定删除最后的元素,因为是无序的
s.pop()

输出结果:

{1, 2, 3, 5}

set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:

s = {1, 2, 3}
s2 = {2, 3, 4}
print(s & s2)
print(s | s2)

输出结果:

{2, 3}
{1, 2, 3, 4}

set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”,所以key不能是list等。

其他一些方法:

# 清空内容
# s.clear()

# 返回 A中存在,B中不存在的元素
s = {1, 2, 3}
s2 = {1, 3, 4}
print(s.difference(s2))

# 返回 A中存在,B中不存在的元素,不用新变量来接收,直接更新A的集合(从当前集合中删除和B中相同的元素)
print(s.difference_update(s2))
print(s2.difference(s))

# 返回A和B的交集
print(s.intersection(s2))

# 返回A和B的交集,交更新给A
print(s.intersection_update(s2))

# 是否不相交,如果没交集则返回True
print(s.isdisjoint(s2))

# A是否是B的子集
print(s.issubset(s2))

# A是否是B的父集
print(s.issuperset(s2))

# 返回 A中存在,B中不存在的元素和B中存在,A中不存在的元素的总和
print(s.symmetric_difference(s2))

# 返回A和B的并集
print(s.union(s2))

# 更新集合,即批量添加
s.update([11,22,33])

课外知识

range()方法,用来获取指定范围内的数,只有在拿数据的时候才会动态生成,不占内存。比如:

# 获取的值是取第一个值1,不取最后的值10,中间每隔2拿下一个数
for item in range(1, 10, 2):
    print(item)

输出结果:

1
3
5
7
9

比如:

for item in range(10, 1, -2):
    print(item)

输出结果:

10
8
6
4
2

练习题

1.有两个dict

old_dict = {"#1": 11, "#2": 22, "#3": 100}
new_dict = {"#1": 33, "#4": 24, "#7": 150}

要求一:相同key的new_dict中的值更新到old_dict中

要求二:old_dict中存在且new_dict中不存在的元素在old_dict中全部删除。

要求三:new_dict中存在且old_dict中不存在的元素在old_dict中全部添加。

代码如下:

old_key = set(old_dict.keys())
new_key = set(new_dict.keys())

for key in old_key.intersection(new_key):
    old_dict[key] = new_dict[key]

for key in new_key.difference(old_key):
    old_dict[key] = new_dict[key]

for key in old_key.difference(new_key):
    old_dict.pop(key)

print(old_dict)

输出结果:

{'#1': 33, '#4': 24, '#7': 150}

2.有如下值集合 [11,22,33,44,55,66,77,88,99,…],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。即: {‘k1’: 大于66的所有值, ‘k2’: 小于66的所有值}

代码如下:

result = {"k1": [], "k2": []}
for item in list(range(11, 101, 11)):
    if item > 66:
    result["k1"].append(item)
    elif item < 66:
    result["k2"].append(item)
print(result)

输出结果:

{'k1': [77, 88, 99], 'k2': [11, 22, 33, 44, 55]}