欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python 进阶学习笔记之二:常用数据类型(上)

程序员文章站 2022-06-04 09:07:58
...

Python 进阶系列笔记第二篇,第一篇传送门:
Python 进阶学习笔记之一:内置常用类型及方法

6. 日期

在datetime模块中有以下类型 date、datetime、time分别来表示日期、带时间的日期和时间,还有一个用于日期计算的 timedelta。本模块在支持日期时间数学运算的同时,实现的关注点更着重于如何能够更有效地解析其属性用于格式化输出和数据操作。

有两种日期和时间的对象:“无知型“和”感知型“。感知型对象有着用足以支持一些应用层面算法和国家层面时间调整的信息,例如时区和夏令时,来让自己和其他的感知型对象区别开来。无知型对象所代表的是世界标准时间(UTC)、当地时间或者是其它时区的时间完全取决于程序,就像一个数字是代表的是米、英里或者质量完全取决于程序。 无知型对象以忽略了一些现实情况的为代价使得它容易理解和使用。
无知型和感知型之间不适用于基于 timedelta 对象的运算。

6.1 timedelta 对象

timedelta 对象表示两个 date 或者 time 的时间间隔。类描述:class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)。两个 timedelta 之间支持四则运算,timedelta 与 time/datetime之间也支持加减运算(最常用)。

# 小技巧,可以根据timedelta来计算具体秒
>>> from datetime import timedelta
>>> d = timedelta(days=1)
>>> d.total_seconds()
86400.0
>>> d2 = d + timedelta(minutes=1)
>>> d2.total_seconds()
86460.0

6.2 date 对象

首先说明,date 对象是无感知类型的。

date 构造器用法:

# class datetime.date(year, month, day)
d1 = datetime.date(2019, 12, 1)

# classmethod date.today()
d2 = datetime.date.today()

# classmethod date.fromtimestamp(timestamp)
d3 = datetime.date.fromtimestamp(datetime.time.time())

date 常用方法:

d = date()
date(2019, 01, 02).isoformat()    # 返回一个 ISO 8601 格式的字符串, 'YYYY-MM-DD'。例如 '2019-01-02'
classmethod date.fromisoformat(date_string)    # 注意,这是一个类方法,是上面那个方法的逆方法,提供一个 ISO 8601 格式字符串,返回一个 date 对象,如 d = date.fromisoformat('2019-01-02')
# 常用常量
date.year
date.month
date.day

# 常用运算
date2 = date1 + timedelta(days=1)         # 日期是不可变的对象,因此改变后是一个新对象
date2 = date1 - timedelta(days=1)
timedelta = date1 - date2          # 日期差值出来的 timedelta 中的 时分秒会被忽略
date1 < date2

其他常用实例方法

date.replace(year=self.year, month=self.month, day=self.day):返回一个具有同样值的日期,可以通过任何关键字参数给出了某些形参的新值。 例如 d == date(2002, 12, 31),则 d.replace(day=26) == date(2002, 12, 26)
date.strftime(format):返回一个日期指定格式的字符串。如;date(2019, 1, 1).strftime(’%Y-%m-%d’) = ‘2019-01-01’,如果要逆向操作,请参考使用 datetime 的类方法 strptime(),把字符串转成 datetime

6.3 datetime 对象

datetime 对象是一个包含了来自 date 对象和 time 对象所有信息的单一对象。

构造器方法

class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0):其中fold 参数是 3.6 新加的
classmethod datetime.today():返回当前的本地 datetime,tzinfo 值为 None。
classmethod datetime.now(tz=None):返回当前的本地 date 和 time。 如果可选参数 tz 为 None 或未指定,这就类似于 today()
classmethod datetime.utcnow():返回当前 UTC 日期和时间,其中 tzinfo 为 None。 这类似于 now()
classmethod datetime.fromtimestamp(timestamp, tz=None):返回指定时间戳和时区的当地时间
classmethod datetime.strptime(date_string, format):给定一个字符串格式,和对应格式的时间字符串,返回一个 datetime 对象
classmethod datetime.combine(date, time, tzinfo=self.tzinfo):返回一个新的 datetime 对象,对象的日期数值等于给定的 date 对象的数值,时间数值等于给定的 time 对象的数值。 如果提供 tzinfo 参数,其值会被用来设置结果的 tzinfo 属性,否则将会使用 time 参数的 tzinfo 属性。

属性及实例方法

常用属性:year、month、day、hour、minute、second、microsecond、tzinfo
常见实例方法:
datetime.date():返回具有同样 year, month 和 day 值的 date 对象
datetime.time():返回具有同样 hour, minute, second, microsecond 和 fold 值的 time 对象。 tzinfo 为 None。
datetime.timetz():返回具有同样 hour, minute, second, microsecond, fold 和 tzinfo 属性值的 time 对象。
datetime.replace(year=self.year, month=self.month, day=self.day, hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0):返回一个具有同样属性值的 datetime,除非通过任何关键字参数指定了某些属性值。3.6 新版功能: 增加了 fold 参数。
datetime.astimezone(tz=None):返回一个具有新的 tzinfo 属性 tz 的 datetime 对象,并会调整日期和时间数据使得结果对应的 UTC 时间与 self 相同,但为 tz 时区的本地时间。
datetime.strftime(format):返回一个由显式格式字符串所指明的代表日期和时间的字符串。要获取格式指令的完整列表请参阅 【时间格式化规则】

6.4 time 对象

一个 time 对象代表某个日期内的(本地)时间,它独立于任何特定日期,并可通过 tzinfo 对象来调整,还有一点继续提一下,有感知time和无感知time不能进行比较操作。

构造器方法:

class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0):所有的参数都是可选的

常用属性及方法

常用类属性:
hour、minute、second、microsecond、tzinfo
常用实例方法:
time.replace(hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0):返回一个具有同样属性值的 time,除非通过任何关键字参数指定了某些属性值,fold参数为3.6版本新增。

7. collections — 容器数据类型

这个模块实现了几个特定目的的容器,提供了某些场景下Python标准内建容器 dict , list , set , 和 tuple 的替代选择。

7.1 ChainMap 对象:

ChainMap 类是为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理。它通常比创建一个新字典和多次调用 update() 要快很多。

>>> baseline = {'music': 'bach', 'art': 'rembrandt'}
>>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}
>>> m = ChainMap(adjustments, baseline)
>>> list(m)
['music', 'art', 'opera']
>>> m['art']
van gogh

7.2 Counter 对象:

一个计数器工具提供快速和方便的计数,一个 Counter 是一个 dict 的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。

>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
...     cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})

>>> c = Counter('abracadabra'). # 使用字符串序列创建一个计数器,会自动统计字符串序列中每个字母出现的次数
>>> c..most_common(3)  # most_common([n]),3.1+版本中新增方法,n不为空时,返回计数前N的组合

7.3 deque 对象:

class collections.deque([iterable[, maxlen]]):返回一个双向队列对象,从 iterable (迭代对象) 数据创建。如果 iterable 没有指定,新队列为空。Deque 支持线程安全,内存高效添加(append)和弹出(pop),从两端都可以,两个方向的大概开销都是 O(1) 复杂度。虽然 list 对象也支持类似操作,不过这里优化了定长操作和 pop(0) 和 insert(0, v) 的开销。它们引起 O(n) 内存移动的操作,改变底层数据表达的大小和位置。如果 maxlen 没有指定或者是 None ,deques 可以增长到任意长度。否则,deque就限定到指定最大长度。一旦限定长度的deque满了,当新项加入时,同样数量的项就从另一端弹出。

deque 支持典型的队列操作,由于是双端队列,弹出操作和添加操作都有分别对应两端的成套方法。队列也是列表的一种,大部分的列表操作队列也支持,包括迭代,清洗,len(d), reversed(d), copy.copy(d), copy.deepcopy(d), 成员测试 in 操作符,和下标引用 d[-1] 。
常见操作:

from collections import deque
d = deque('ghi')
for elem in d: 
	print(elem)

d.append('j')
d.appendleft('f')
d.pop()
d.popleft()
list(d)
list(reversed(d))
d.extend('jkl')       # 从右侧添加一个序列
d.extendleft('abc') 

成员方法rotate是个很有意思的方法,这个方法实现了队列头尾衔接式循环。 rotate(n): 向右循环移动 n 步。 如果 n 是负数,就向左循环。向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。

>>> from collections import deque
>>> q1 = deque('abc')
>>> q1
deque(['a', 'b', 'c'])
>>> q1.rotate(1)
>>> q1
deque(['c', 'a', 'b'])
>>> q1.rotate(-2)
>>> q1
deque(['b', 'c', 'a'])

7.4 defaultdict 对象

class collections.defaultdict([default_factory[, ...]]):返回一个新的类似字典的对象。 defaultdict 是内置 dict 类的子类。它重载了一个方法并添加了一个可写的实例变量。其余的功能与 dict 类相同。
关键在于初始化时的参数 default_factory,default_factory 提供后,如果使用 d[key]形式获取值,key 不存在时,不会得倒 KeyError错误,defaultdict 会自动调用 __miss__(key)方法,而这个 __miss__方法会调用 default_factory来构建一个默认值。

# 最基本用法
from collections import defaultdict

def factory():
    return 'miss'

md = defaultdict(factory)
md['a'] = 'a'
print(md['b'])    # b 在字典对象中并不存在,如果是普通的dict,会报KeyError的错,使用defaultdict 则会返回默认值

如果想根据传入的key来定制返回值的话,我们可以继承 defaultdict 来实现自己的 __miss__ 方法:

from collections import defaultdict
class myDefaultDict(defaultdict):
    def __missing__(self, key):
        return str(key) * 2

md2 = myDefaultDict()
md2['a'] = 'a'

print(md2['b'])      # 这里根据 __miss__ 的规则会返回 ‘bb’

7.5 namedtuple() 命名元组的工厂函数

命名元组赋予每个位置一个含义,提供可读性和自文档性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。命名元组实例没有字典,所以它们要更轻量,并且占用更小内存。
collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):部分参数时在3.1后续版本中陆续新增的,具体作用和版本支持请参照:https://docs.python.org/zh-cn/3/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields

基本用法:

>>> Po = namedtuple('Point', ['x', 'y'])
>>> p = Po(1, 2)
>>> p[0] + p[1]       
3
>>> p.x + p.y         
3
>>> p
Point(x=1, y=2)

>>> d = {'x': 11, 'y': 22}
>>> Point(**d)        # 要将字典转换为命名元组,请使用 ** 运算符

除了继承元组的方法,命名元组还支持三个额外的方法和两个属性。为了防止域名冲突,方法和属性以下划线开始。
classmethod somenamedtuple._make(iterable):类方法从存在的序列或迭代实例创建一个新实例。

>>> Point = namedtuple('Point', ['x', 'y'])
>>> t = [11, 22]
>>> Point._make(t)
Point(x=11, y=22)

这个方法尤其在格式化从数据库中取的值时有用

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
	print(emp.name, emp.title)

还有解析 CSV 文件时

import csv

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
 	print(emp.name, emp.title)

somenamedtuple._replace(**kwargs):返回一个新的命名元组实例,并将指定域替换为新的值

>>> p = Point(x=11, y=22)
>>> p._replace(x=33)
Point(x=33, y=22)

7.6 OrderedDict 对象:

由于内置的 dict 类获得了记住插入顺序的能力(在 Python 3.7 中保证了这种行为),OrderedDict变得不那么重要了。但其特殊的方法,在某些场景下还是很有效的。
popitem(last=True):有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。since 3.1+
move_to_end(key, last=True):将现有 key 移动到有序字典的任一端。 如果 last 为真值(默认)则将元素移至末尾;如果 last 为假值则将元素移至开头。如果 key 不存在则会触发 KeyError。since 3.2+

——————

继续阅读请点击:Python 进阶学习笔记之二:常用数据类型(下)

相关标签: Python 进阶