Python-数据类型

TomTao626 于 2019-04-12 发布
🥰本站访客数 👀本文阅读量

Python 中的可变和不可变数据类型(基于地址而言)

  • 可变类型:当变量的值更改,那么变量对应的内存地址不会更改, 对象的 id 值不变;
  • 不可变类型:当变量的值更改,那么变量对应的内存地址也会更改,对象的 id 值会变化;
  • python中的数据类型主要有 整型 字符串 元祖 集合 列表 字典
#可以通过id()函数查看变量的地址
# 整型
a = 1
print(id(a), type(a)) # 4457200368 <class 'int'>
a = 2
print(id(a), type(a)) # 4457200400 <class 'int'>
# 你会发现整型变量a值发生了更改,地址也发生了变化,所以整型是不可变数据类型

# 字符串
b = "tomato"
print(id(b), type(b)) # 4473099632 <class 'str'>
b = "9527"
print(id(b), type(b)) # 4473101296 <class 'str'>
# 字符串变量b值发生了更改,地址也发生了变化,所以字符串是不可变数据类型

# 元祖 也称作可读列表 值不能被修改 但是我们可以在元组的元素中存放一个列表,通过更改列表的值来查看元组是属于可变还是不可变
c1 = ['1','2']
c = (1,2,c1)
print(c,id(c),type(c))  # (1, 2, ['1', '2']) 4395721024 <class 'tuple'>
c1[1] = 'tom'
print(c,id(c),type(c))  # (1, 2, ['1', 'tom']) 4395721024 <class 'tuple'>
# 虽然元组数据发生改变,但是内存地址没有发生了改变,但是不可以以此来判定元组就是可变数据类型。回头仔细想想元组的定义就是不可变的。
# 修改了元组中列表的值,但是因为列表是可变数据类型,所以虽然在列表中更改了值,但是列表的地址没有改变,列表在元组中的地址的值没有改变,所以也就意味着元组没有发生变化。
# 可以认为元组是不可变数据类型,因为元组是不可变的。

# 集合 常用来进行去重和关系运算,集合是无序的。
d = {1, '9527', 2, 3, 4, 'a', 'b'}
print(d, id(d), type(d)) # {1, 2, 3, 4, 'a', '9527', 'b'} 4377626656 <class 'set'>
d.add('tomato')
print(d, id(d), type(d)) # {1, 2, 3, 4, 'a', '9527', 'b', 'tomato'} 4377626656 <class 'set'>
# 集合d虽然值发生了更改,但地址没有变化,所以集合是可变数据类型

# 列表
e_list = [1,2,'a', 'b', 9527]
print(e_list, id(e_list), type(e_list)) # [1, 2, 'a', 'b', 9527] 4345474112 <class 'list'>
e_list.append('6666')
print(e_list, id(e_list), type(e_list)) # [1, 2, 'a', 'b', 9527, '6666'] 4345474112 <class 'list'>
# 列表e_list虽然值发生了更改,但地址没有变化,所以列表是可变数据类型

# 字典 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据。
# python对key进行哈希函数运算,根据计算的结果决定value的存储地址,所以字典是无序存储的。但是在3.6版本后,字典开始是有序的,这是新的版本特征。
# 字典的key值可以是整型,字符串,元组,但是不可以是列表,集合,字典。
f_dict = {'a':'test1', 'b':'test2'}
print(f_dict, id(f_dict), type(f_dict)) # {'a': 'test1', 'b': 'test2'} 4337296256 <class 'dict'>
f_dict.update(dict(test5=(1,2,)))
print(f_dict, id(f_dict), type(f_dict)) # {'a': 'test1', 'b': 'test2', 'test5': (1, 2)} 4337296256 <class 'dict'>
# 字典f_dict虽然值发生了更改,但地址没有变化,所以字典是可变数据类型
"""
    数据类型	可变/不可变
     整型	   不可变
     字符串	   不可变
     元组	   不可变
     列表	   可变
     集合	   可变
     字典	   可变
     可变数据类型即公用一个内存空间地址,不可变数据类型即每产生一个对象就会产生一个内存地址
"""
  • 不可变对象不允许对自身内容进行修改。如果我们对一个不可变对象进行赋值,实际上是生成一个新对象,再让变量指向这个对象。
  • 可变对象则可以对自身内容进行修改, 虽然对象的值发生了变化,但是地址没变,还是原来那个对象。
  • 可变对象于不可变对象本身的不同仅在于一个可以修改变量的值,而另一个不允许
  • 基于这一设定,两者在功能上的最大区别就是:不可变对象可以作为字典 dict 的键 key,而可变对象不行。
  • 另外,明白了可变与不可变的区别,一些方法的效果也就自然理解了:
s = 'abc'
s2 = s.replace('b', 'd')
print('s', s)
print('s2', s2)
m = [1, 2, 3]
m2 = m.reverse()
print('m', m)
print('m2', m2)
# 打印结果
# s abc
# s2 adc
# m [3, 2, 1]
# m2 None
  • 因为 str 是不可变对象,所以它的方法如 replace、strip、upper 都不可能修改原对象,只会返回一个新对象,比如重新赋值才可以。
  • 而 list 是可变对象,它的方法如 reverse、sort、append,都是在原有对象上直接修改,无返回值。
  • 不过,有个特殊情况需要注意:
m = [1, 2, 3]
print('m', m, id(m))
m += [4]
print('m', m, id(m))
m = m + [5]
print('m', m, id(m))
# 打印结果
# m [1, 2, 3] 4477456576
# m [1, 2, 3, 4] 4477456576
# m [1, 2, 3, 4, 5] 4477456832
  • m = m + 和 m += 虽然是一样的结果,但 m 指向的对象却发生了变化。
  • 原因在于,前者是做了赋值操作,而后者其实是调用的 iadd 方法。
  • 如果我们就是需要产生一个 list 对象的副本,可以通过 [:]:
m = [1, 2, 3]
print('m', m, id(m))
n = m[:]
print('n', n, id(n))
n[1] = 4
print('m', m)
print('n', n)
# 打印结果
# m [1, 2, 3] 4532969728
# n [1, 2, 3] 4532969664
# m [1, 2, 3]
# n [1, 4, 3]
  • 这样对 n 的修改便不再会影响到 m,因为它们已不是同一个对象。
  • 请写出下面代码的输出结果
    m = [1, 2, [3]]
    n = m[:]
    n[1] = 4
    n[2][0] = 5
    print(f"m={m}")
    print(f"n={n}")
    # 打印结果
    # m=[1, 2, [5]]
    # n=[1, 4, [5]]
    
  • 不可变类型:改变了存储单元内容的对象不再被认为是原对象。
  • 可变类型:改变了存储单元内容的对象仍然被认为是原对象。

is 和 == 有什么区别?

is:是调用id()函数 比较两个id值是否相等,是否指向同一个内存地址,如果id相等,就是同一个实例对象
==:是调用eq()函数 比较两个对象的值,值相等就返回True,但是id不一定相等

python大小写转换和字母统计

# 每个单词首字母大写 title()
a = "tomato abc"
print(a.title())  # Tomato Abc

# 句子第一个字母大写 capitalize()
print(a.capitalize()) # Tomato abc

# 所有字母大写小写:upper()、lower()
# upper() 小写字母转大写
b = "totmTaoHxTYt66"
print(b.upper()) # TOMTAOHXY66
# lower() 大写字母转小写
print(b.lower()) # tomtaohxy66

# 统计某个字母出现的次数:count('t') 注意:区分大小写
print(b.count('t')) # 3
print(b.count('T')) # 2

字符串,列表,元组如何反转;反转函数 reversereversed 的区别

# 列表反转 可迭代对象(实现__iter__即可)
# reverse和reversed都是列表反转的一个方法,前者返回一个反转后的列表,后者返回反转的迭代器对象,只要是可迭代对象,都可以调用reversed()
# 反转后的迭代器可使用for循环或者调用next方法取出元素
x = [1,2,3,4,5]
x.reverse()
print(x) # [5, 4, 3, 2, 1]

# reversed: reversed()的作用之后,返回的是一个把序列值经过反转之后的迭代器,
ls2 = [4, 5, 6]
print(reversed(ls2)) # 迭代器对象的内存地址 <list_reverseiterator object at 0x0003545427A5454682E8>
print(list(reversed(ls2))) # [6, 5, 4]

# 字符串反转方法1
str1 = 'abced12345'
str2 = ''.join(reversed(str1)) # 使用join拼接反转后的字符
print(str2) # 'abced12345'

# 字符串反转方法2
str3 = str1[::-1]
print(str3) # 54321decba

含有多种符号的字符串分割方法?

# 1 使用 []+,中括号里面写上所有的符号,后面的 + 表示可以出现多次,类似于正则表达式
import re
a = "ab;cd%e\tfg,,jklioha;hp,vrww\tyz"
_a = re.split(r'[;%\t,]+', a)
print(_a) # ['ab', 'cd', 'e', 'fg', 'jklioha', 'hp', 'vrww', 'yz']

b = "info:tomato 33 test;666"
_b = re.split(r':|;| ', b)
print(_b) # ['info', 'tomato', '33', 'test', '666']
# 2 使用|表示或

嵌套列表转换为列表,字符串转换为列表

# 嵌套列表转换为列表
ls = [[1,2,3], [4,5,6],[7,8,9]]
ls2 = [j for i in ls for j in i]
print(ls2) # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 字符串转换为列表
a = 'a,b,c,1,2,3,4,x,y,z'
ls3 = a.split(',')
print(ls3) # ['a', 'b', 'c', '1', '2', '3', '4', 'x', 'y', 'z']

列表合并的常用方法

# extend扩展合并
a = [1,2,3]
b = ['a', 'b', 'c']
a.extend(b)
print(a) # [1, 2, 3, 'a', 'b', 'c']
# 列表相加
print(a+b) # [1, 2, 3, 'a', 'b', 'c']
# for循环遍历 append
for i in a:
    b.append(i)
print(b) # [1, 2, 3, 'a', 'b', 'c']

列表如何去除重复的元素

# 不改变原有顺序
# set集合和sorted
ls_one = [1, 2, 5, 3, 8, 5, 2, 10, 9]
def sort_list_index(ls_one: list) -> list:
    ls_one_new = sorted(set(ls_one), key=ls_one.index)
    return ls_one_new
print(sort_list_index(ls_one))  # [1, 2, 5, 3, 8, 10, 9]

# for循环+新列表
ls_new = list()
# for i in ls_one:
#     if i not in ls_new:
#         ls_new.append(i)
ls_one = [i for i in ls_one if i not in ls_new]
print(sort_list_index(ls_one))  # [1, 2, 5, 3, 8, 10, 9]

# keys()方法
form_list = list({}.fromkeys(ls_one).keys())
print(form_list) # [1, 2, 5, 3, 8, 10, 9]

# 改变原有顺序
# set集合
print(list(set(ls_one))) # [1, 2, 3, 5, 8, 9, 10]

# itertools.grouby
import itertools
ls_one.sort()
ls_two = list()
ls_it = itertools.groupby(ls_one)
print([k for k,_ in ls_it]) # # [1, 2, 3, 5, 8, 9, 10]

列表数据如何筛选,筛选出符合要求的数据

# 生成一个人随机数组成的列表
import random
data = [random.randint(-10, 100) for _ in range(10)]
print(data) # [-1, 10, -2, 3, 4, 1, 9, -5, -10, 2]
# for 循环,筛选出符合条件的数据,添加到一个空列表中
new_data = list()
for i in data:
    if i > 0:
        new_data.append(i)
print(new_data) # [10, 3, 4, 1, 9, 2]
# 过滤函数 filter 配合匿名函数 lambda 表达式
result = list(filter(lambda x: x > 0, data))
print(result) # [10, 3, 4, 1, 9, 2]
# 列表解析(推荐使用,效率最高)
data = [i for i in data if i > 0]
print(data) # [10, 3, 4, 1, 9, 2]

字典中元素的如何排序

# sorted()排序 
# 字典根据键从小到大排序
info = {'name': 'Gage', 'age': 25, 'sex': 'man'}
print(sorted(info.items(), key=lambda x:x[0])) # [('age', 25), ('name', 'Gage'), ('sex', 'man')]

字典如何合并;字典解包是啥

# 字典如何合并:a.update(b)
a = {"name":"test", "age":9527}
b = {"sex":True, "weight":"188kg"}
a.update(b)
print(a) # {'name': 'test', 'age': 9527, 'sex': True, 'weight': '188kg'}

# 字典解包:{**a,**b} 也就是合并
print({**a}) # {'name': 'test', 'age': 9527}
print({**a, **b}) # {'name': 'test', 'age': 9527, 'sex': True, 'weight': '188kg'}

# 合并下面两个字典 c = {"A":1,"B":2}, d = {"C":3,"D":4}
c = {"A":1,"B":2},
d = {"C":3,"D":4}
print({**c, **d})

字典推导式使用方法;字典推导式如何格式化cookie值

# 字典推导式使用方法 和列表生成式使用方法一致 
# 字典键值交换
a = {"name":"test", "age":9527}
print(a.items()) # dict_items([('name', 'test'), ('age', 9527)])
print(a.values()) # dict_values(['test', 9527])
# 方法1 字典推导式
print({v:k for k,v in a.items()})  # {'test': 'name', 9527: 'age'}
# 方法2 zip()+dict()
print(dict(zip(a.values(),a.keys()))) # {'test': 'name', 9527: 'age'}

# 字典推导式如何格式化cookie值
cookie = "show_id=100126;username=\u968f\u52a9\u6d4b\u8bd5-Tom2222;email=751825253@qq.com;role_code=admin;job=\u7ba1\u7406\u5458;department=test;parent_id=1;app_ver=1.2.0;status=true;mobile=18372620761;phone=+86-13073670883;gender=1;qq=1;wechat=1;remark=111;add_time=1596203920;upd_time=1619862585"
#将cookie格式化成一个字典 先根据;将其分割成一个list,再根据=分隔出key和vale
cookie = {i.split("=")[0]:i.split("=")[1] for i in cookie.split(";")}
print(cookie)  # {'show_id': '100126', 'username': 'Tom2222', 'email': '751825253@qq.com', 'role_code': 'admin', 'job': '666', 'department': 'test', 'parent_id': '1', 'app_ver': '1.2.0', 'status': 'true', 'mobile': '18372620761', 'phone': '86-13073670883', 'gender': '1', 'qq': '1', 'wechat': '1', 'remark': '111', 'add_time': '1596203920', 'upd_time': '1619862585'}

zip 打包函数的使用?元组或者列表中元素生成字典?

# zip打包函数的使用 zip()函数传入一个可迭代对象,然后元素一一对应组成一个元祖,然后将所有元祖打包成一个列表
# zip 方法在 Python 2 和 Python 3 中的不同:在 Python 3 中为了减少内存,zip() 返回的是一个对象。如需展示列表,需手动 list() 转换。
a = [1,2,3]
b = ['a', 'b', 'c']
ls = zip(a, b)
print(ls) # <zip object at 0x101d780c0>
print(list(ls)) # 在 Python 3 中为了减少内存,zip() 返回的是一个对象。如需展示列表,需手动 list() 转换。

# 元组或者列表中元素生成字典
print(dict(list(ls)))  # {1: 'a', 2: 'b', 3: 'c'}
# 示例
l = ['a', 'b', 'c', 'd', 'e','f']
l1 = list(zip(l[:-1],l[1:]))
print(l1) # [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('e', 'f')]
print(dict(l1)) # {'a': 'b', 'b': 'c', 'c': 'd', 'd': 'e', 'e': 'f'}

# 把元组 ("a","b") 和元组 (1,2),变为字典 {"a":1,"b":2}
tuple_c = ("a","b",)
tuple_d = (1,2,)
print(dict(zip(tuple_c, tuple_d))) # {'a': 1, 'b': 2}

字典的键可以是哪些类型的数据?

字典的键是可以被hash的,可以被hash的对象就是不可变数据,不可变数据可以作为字典的键,比如数字、字符串、元组都可以
列表、集合、字典是可变类型不是可hash对象,所以不能用列表做为字典的键

变量的作用域

在 Python 中,定义一个变量,该变量的作用域是该变量被赋值时候所处的位置决定的
当一个变量在函数内部被定义和赋值,该变量就是一个局部变量,在函数外部使用就会出现错误
函数变量作用域的搜索顺序:
    1.本地作用域(Local)、
    2.当前作用域被嵌入的本地作用域(Enclosing locals)、
    3.全局/模块作用域(Global)、
    4.内置作用域(Built-in)

获取字符串”123456“最后的两个字符。

s = "98755tomtao42"
# 获取最后三位
print(s[-3::]) # o42

一个编码为 GBK 的字符串 S,要将其转成 UTF-8 编码的字符串,应如何操作?

s = "shenmeguiya"
gbk_s = s.encode("gbk") # b'shenmeguiya'
gbk_s.decode("utf-8", 'ignore') # 'shenmeguiya'

给定两个 list,A 和 B,找出相同元素和不同元素

A = [1,2,3,'a','x']
B = ['a',2,'b','zz']
print(f"A和B相同元素(交集)是{set(A)&set(B)}") # A和B相同元素(交集)是{2, 'a'}
print(f"A和B不同元素(差集)是{set(A)^set(B)}") # A和B不同元素(差集)是{'zz', 1, 3, 'x', 'b'}

打乱列表的元素

import random
l = [1,2,3,'a','x',9527,'z','中国']
random.shuffle(l)
print(l) # [2, 9527, '中国', 'a', 3, 'x', 'z', 1]

字典操作中del和pop的区别

"""
    del是根据字典内元素索引位置删除,没有返回值
    pop是根据索引弹出一个值,然后接受其返回值
"""
a = {'name':'tom', 'age':18, 'sex':'male', 'grade':9527}
print(a.pop('name')) # tom # 弹出字典a中key为name的元素 并返回其弹出值
del a['age'] # 删除字典a中key为age的元素
print(a) # {'name': 'tom', 'sex': 'male', 'grade': 9527}

a=”hello” 和 b=”你好” 编码成 bytes 类型

a = "hello"
b = "你好"
print(b"hello")  # b'hello'
print(bytes(b, 'utf-8'))  # b'\xe4\xbd\xa0\xe5\xa5\xbd'
print(b.encode("utf-8"))

元祖不支持修改,但是元祖内的元素本身是可变数据类型,那么就支持修改

a = (1,2,3,[4,5,6,7],8)
# a[2] = 2 # 会出现异常 TypeError: 'tuple' object does not support item assignment 因为元祖不支持修改
print(list(a)) # [1, 2, 3, [4, 5, 6, 7], 8] 元祖转数组
print(tuple(list(a)))  # (1, 2, 3, [4, 5, 6, 7], 8) 数组转元祖

# 下面的代码输出的结果是什么?
a = (1,2,3,[4,5,6,7],8)
a[3][0] = 2
print(a) # (1, 2, 3, [2, 5, 6, 7], 8)
# 如果元组里面元素本身就是可变数据类型,比如列表,那么在操作这个元素里的对象时,其内存地址也是不变的。
# a[3] 对应的元素是列表,然后对列表第一个元素赋值,所以最后的结果是: (1,2,3,[2,5,6,7],8)

如何生成一个 16 位的随机字符串

import random
import string
print(''.join(random.choice(string.printable) for i in range(16))) # a0TN_)QA6PFVeiHK

python 中生成随机整数、随机小数、0–1 之间小数方法

import random
# 随机整数
print(random.randint(1,10)) # 7
# 随机小数
print(random.random()) # 0.021827474121851265
# 0--1 之间小数方法
print(random.uniform(0,1)) # 0.12594292005935803

<div class="nam">Python</div>,用正则匹配出标签里面的内容(“Python”),其中 class 的类名是不确定的。

import re
s = '<div class="nam">中国</div>'
print(re.findall(r'<div class=".*">(.*?)</div>', s)) # ['中国']

dictfromkeys 的用法

key = ('info',)
print(dict.fromkeys(key, ['a',1,'9527'])) # {'info': ['a', 1, '9527']}

正则表达式输出汉字

import re
s = '"not 404 found 中>国 2018 hwhdjs=-+? 我爱你"'
r = '[a-zA-Z0-9’!"#$%&\'()*+,-./:;<=>?@,。?★、…【】《》?“”‘’![\\]^_`{|}~]+\s?'
print(re.sub(r, '', s)) # 中国 我爱你

s = “ajldjlajfdljfddd”,去重并从小到大排序输出”adfjl”?

s = "ajldjlajfdljfddd"
print(set(s)) # {'j', 'f', 'l', 'd', 'a'}
print(sorted(s)) # ['a', 'a', 'd', 'd', 'd', 'd', 'd', 'f', 'f', 'j', 'j', 'j', 'j', 'l', 'l', 'l']
print(sorted(set(s))) # ['a', 'd', 'f', 'j', 'l']
print(''.join(sorted(set(s))))

Python 获取当前日期

import time
import datetime
print(datetime.datetime.now()) # 2021-12-02 14:48:09.273591
print(time.strftime("%Y-%m-%d %H:%M:%s")) # 2021-12-02 14:48:09

获取请求头的参数

from urllib.parse import urlparse, parse_qs
s = "/get_feed_list?version_name=5.0.9.0&device_id=12242&channel_name=google"
def splitvalue(value):
    url = {'site':urlparse(value).path}
    url.update(parse_qs(urlparse(value).query))
    return url

print(splitvalue(s))  # {'site': '/get_feed_list', 'version_name': ['5.0.9.0'], 'device_id': ['12242'], 'channel_name': ['google']}

json 序列化时,可以处理的数据类型有哪些?如何定制支持 datetime 类型?

可以处理的数据类型是 str、int、list、tuple、dict、bool、None, 因为 datetime 类不支持 json 序列化,所以我们对它进行拓展。 ```python # 自定义时间序列化 # JSONEncoder 不知道怎么去把这个数据转换成 json 字符串的时候,它就会去调 default()函数, # 所以都是重写这个函数来处理它本身不支持的数据类型,default()函数默#认是直接抛异常的。 import json import datetime class DateToJson(json.JSONEncoder):
def default(self, obj):
    if isinstance(obj, datetime.datetime): 
        return obj.strftime('%Y-%m-%d %H:%M:%S')
    elif isinstance(obj, datetime.date): 
        return obj.strftime('%Y-%m-%d')
    else: 
        return json.JSONEncoder.default(self, obj) d = {'name':'cxa', 'data':datetime.datetime.now()} print(json.dumps(d, cls=DateToJson)) # {"name": "cxa", "data": "2021-12-02 25\uff1a23\uff1a20"} ```