Python日志

Python日志,第1张

Python 学习内容:


第一章

repr函数,获得以python的方式显示内容。


>>>print(repr('hello,\nworld')
>>> 'hello,\nworld'

python 中三引号的长字符串可以换行。


>>>print('''hello world;
hello,tomorrow;''')

关于原始字符串 r:
几乎可以包含任何字符,但是需要对引号进行转义,如:

print(r'let\'s go')

另外,转义字符’\‘,不能放在末尾,python无法判断语句是否结束,会出错!


第一张了解到的函数

m = abs(-1)  # abs(number)  返回指定数的绝对值
print(m)

m= bytes('hello', encoding='utf-8')
print(m)

import cmath
m= cmath.sqrt(9)
print(m)

print(help(print))

input('something')

import math
m = math.ceil(3.1)
print(m,type(m))

m1 = math.floor(3.1)
print(m1,type(m1))

m2 = round(3.1)
print(m2,type(m2))

m2 = round(3.5)
print(m2,type(m2))

m2 = round(4.5)
print(m2,type(m2))

m = pow(2,3,5)
print(m)

m = repr('hello,\nworld')
print(m, type(m))

str()

  • 完成第一章

第二章

数据结构是以某种方式(如通过编号)组合起来的数据元素(如数、字符乃至其他数据结构)集合。


在Python中,最基本的数据结构为序列(sequence)


Python支持一种数据结构的基本概念,名为容器(container)。


容器基本上就是可包含其他对象的对象。


两种主要的容器是序列(如列表和元组)和映射(如字典)
有一种既不是序列也不是映射的容器,它就是集合(set)


简单的练习:

years = input('enter years:')
months = input('enter month(1-12):')
days = input('enter day(1-31):')

Months = ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月',]
months_num = int(months)
print(Months[months_num-1], days+'日', years)

关于切片:
如果第一个索引指定的元素位于第二个索引指定的元素后面(在这里,倒数第3个元素位于第1个元素后面),结果就为空序列

另外,如果步长为正数,起始索引的位置要在终止索引的前面,不然就返回空
如果步长为负数,起时索引的位置要在终止索引的后面,不然就返回空
如果省略了起时或者终止索引,python会自己判断正确的方式。



简单的练习:

name = input('enter your name:')
mid_name = (58-len(name))//2

print(' '*30 + '+' + '-'*58 + '+')
print(' '*30 + '|' + '-'*58 + '|')
print(' '*30 + '|' + '-'*58 + '|')
print(' '*30 + '|' + '-'*mid_name + name + '-'*mid_name + '|')
print(' '*30 + '|' + '-'*58 + '|')
print(' '*30 + '|' + '-'*58 + '|')
print(' '*30 + '+' + '-'*58 + '+')

成员资格检查 in or not in ,用来判断元素是否在序列里,返回布尔值。



还有几个常用的函数, len(), min(), max()

’ [符号或者元素] '.join(序列) :将序列里的元素通过某种元素或者符号连成字符串。



列表的一些方法:

list[索引] = 元素
del语句,删除列表的元素
append()  # 在列表的末尾添加元素
clear() # 清空列表
copy() # 浅复制,只对第一层有用,对嵌套层没有用
deepcopy()  # 深赋值,对嵌套层也有用
count() # 元素在列表中出现的次数
extend()  # 可对列表进行拓展,并生成全新的列表 区别于列表的拼接,拼接并不会改变原列表
index() # 返回列表中元素的索引
insert() # 在索引位置插入某元素
pop()  # 默认d出列表最后的元素,也可指定d出元素的索引, 有返回值
remove() # 移除列表中的元素,如果有多个则移除前面的一个
reverse() # 列表反序
sort() # 排序,可指定排序的key 和 reverse ,方法,永久排序,无返回值, 列表方法
sorted() # 函数,临时排序,返回列表, 可以对字典排序,只返回字典键的列表
lambda x :x*2  # 可以看成定义了一个函数,x是形参,return 一个结果,可以有多个参数,表达式最多只有一个

关于sort方法的练习:

class Student:
    def __init__(self, name, grade, age):
        self.name = name
        self.grade = grade
        self.age = age

    def __repr__(self):
        return repr((self.name, self.grade, self.age))

    def weighted_grade(self):
        return 'CBA'.index(self.grade) / float(self.age)

student_tuples = [
        Student('john', 'A', 15),
        Student('jane', 'B', 12),
        Student('dave', 'B', 10),]
m =sorted(student_tuples, key=lambda student: student.weighted_grade())
print(m)

函数reversed。


这个函数不返回列表,而是返回一个迭代器

  • 完成第二章

第三章 所有标准序列 *** 作(索引、切片、乘法、成员资格检查、长度、最小值和最大值)都适用于字符串

格式字符串 “ %” 和模板字符串“ $”,和字符串方法 format。


格式字符串:% 当作占位符,s表示转换成字符串,除了s还有其他的格式符。





模板字符串:


使用关键字的方式传递内容,需要导入相关的模块。



强大的format方法:
format 方法非常灵活:可以像这样按照位置顺序替换{}里的内容,也可以在{}里放置索引。




索引的位置和顺序可随意放置:

也可以使用关键字参数,同时在:后可以设置具体的格式。


比如.2f 就是保留小数点后两位。



python3.6以后还可以使用一种简写 f字符串。




另外还有:
字段名:索引或标识符,指出要设置哪个值的格式并使用结果来替换该字段。


除指定值外,还可指定值的特定部分,如列表的元素。



可以像这样使用关键字和位置来设置:

也可以使用关键字和索引来表示(位置参数要在关键字参数前面):

不能同时使用位置和索引,换句话说,不能同时使用手工排序和自动排序,这样会显得很混乱。




另外,除了使用直接提供的值以外,还可以访问组成部分,比如访问列表,元组,字符串,字典:

访问字典的时候,字典的键 不需要打引号“”

m = {'name': 'cooper'}
print("{n[name]}".format(n=m))

转换标志:跟在叹号后面的单个字符。


当前支持的字符包括r(表示repr)、s(表示str)和a(表示ascii)。


如果你指定了转换标志,将不使用对象本身的格式设置机制,而是使用指定的函数将对象转换为字符串,再做进一步的格式设置。



感叹号后面加上相应的标志,上述三个标志(s、r和a)指定分别使用str、repr和ascii进行转换。



还可以指定转换的类型。


在冒号后面加上对应的类型说明符。



格式说明符:跟在冒号后面的表达式(这种表达式是使用微型格式指定语言表示的)。


格式说明符让我们能够详细地指定最终的格式,包括格式类型(如字符串、浮点数或十六进制数),字段宽度和数的精度,如何显示符号和千位分隔符,以及各种对齐和填充方式。



在冒号后面直接跟数字,可以设置元素的宽度,数字默认右对齐,字符串默认左对齐。




也可以同时设置宽度和精度,对于数字,符号f来表示精确到小数位


对于字符串可以直接使用小数精确到位数。




还可以添加千位分隔符,位置在宽度和精度之间,适用于数字。


在指定宽度和精度的数前面,可添加一个标志。


这个标志可以是零、加号、减号或空格,其中零表示使用0来填充数字。



from math import pi
"{:+10.3f}".format(pi)
'    +3.142'
"{:-10.3f}".format(pi)
'     3.142'
"{: 10.3f}".format(pi)
'     3.142'

“+” 就在数字前添加+号, “-”和“ ”什么都不添加



要指定左对齐、右对齐和居中,可分别使用<、>和^

"{:<+10.3f}".format(pi)  # + 作为的是符号
'+3.142    '
"{:+<10.3f}".format(pi)  # + 作为的是填充符
'3.142+++++'

注意顺序的区别。


一般来说,填充字符是放在对齐符号的前面。


+ - 比较特殊


还有更具体的说明符=,它指定将填充字符放在符号和数字之间。



"{:=10.3f}".format(-pi)
'-    3.142'
"{:=+10.3f}".format(pi)
'+    3.142'
"{:=-10.3f}".format(pi)
'     3.142'

简单的示例:

width = 35

prince_width = 10
Item_width = 25

header_fmt = "{{:{}}}{{:>{}}}".format(25,10)
fmt  = "{{:{}}}{{:>{}.2f}}".format(25,10)

print('='*35)

print(header_fmt.format('Item', 'Price'))

print('-'*35)

print(fmt.format('apple', 0.5))
print(fmt.format('banana', 0.5))
print(fmt.format('pear', 0.5))

print('-'*35)

说一下这两行代码:

header_fmt = "{{:{}}}{{:>{}}}".format(25,10)
fmt  = "{{:{}}}{{:>{}.2f}}".format(25,10)

print(header_fmt.format('Item', 'Price'))
print(fmt.format('apple', 0.5))

这里用了多层嵌套的关系,后面又重复调用了。


header_fmt = "{{:{}}}{{:>{}}}".format(25,10) 首先要弄明白的是,这行代码的结果是什么? 我们看看: "{{:{}}}{{:>{}}}".format(25,10) '{:25}{:>10}' 返回的是一个字符串,数字分别对应的是最里面的花括号,这相当于将最外面的一层壳拨掉了。


如果没有冒号呢? "{{{}}}{{>{}}}".format(25,10) '{25}{>10}' 跟我们预想的一样,对应的是最里面的花括号。


针对我们这个练习来说,冒号是必要的。


如果没有冒号再进行后面代码的时候就会出问题。


fmt.format('apple', 0.5) 相当于 '{25}{>10}'.format('apple', 0.5) 如果没有冒号,这里的数字就相当于索引了,这样就会报错,索引超出了范围。


'{:25}{:>10}'.format('apple', 0.5) 加上冒号,数字的意思就变成了宽度,一切就正常了。



模块string中比较有用的常量:

一些字符串方法

center方法,可以设置宽度和填充符号。




方法find在字符串中查找子串。


如果找到,就返回子串的第一个字符的索引,否则返回-1。




find方法还可以指定搜索的起点和终点。


(不包含终点)

join是一个非常重要的字符串方法,所合并的序列必须是字符串。


m = 'h','e','l','l','o'
n = ('+'.join(m))
n
'h+e+l+l+o'
用某个元素或者符号连接序列里的字符串

split方法和join相反,它是将字符串以某种元素分隔开,返回一个列表。


n = 'h+e+l+l+o'
n.split('+')
['h', 'e', 'l', 'l', 'o']

lower 方法将字母变小写,supper,变大写,title首字母大写,capitalize一段话的首字母大写。



模块string中的函数capwords,可以做到更为准确的首字母大写。




方法replace将指定子串都替换为另一个字符串,并返回替换后的结果,注意,是都替换。


n = 'is a is'
n.replace('is', 'are')
'are a are'

方法strip将字符串开头和末尾的空白(但不包括中间的空白)删除,并返回删除后的结果。


还有 lstrip 删除左边的空白和rstrip删除右边的空白,也可以在括号内指定要删除的元素。



方法translate与replace一样替换字符串的特定部分,但不同的是它只能进行单字符替换,这个方法的优势在于能够同时替换多个字符,replace一次只能替换一类。



使用translate方法时需要先创建转换表。


table = str.maketrans('ab','zx')
m= 'abbaabba'
m.translate(table)
'zxxzzxxz'
  • 完成第三章

第四章

在字典(以及其他映射类型)中,键必须是独一无二的,而字典中的值无需如此。



字典中的键不能修改,对应的值可以修改。


元组,字符串等不可变的序列可以作为字典的键,数字也可以。


  • 可使用函数dict函数从其他映射(如其他字典)或键-值对序列创建字典。




    也可以用关键字实参的方式创建字典。



  • 字典中的键可以是整数,但并非必须是整数。


    字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或元组。


  • 即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项。


  • 表达式k in d(其中d是一个字典)查找的是键而不是值
  • 相比于检查列表是否包含指定的值,检查字典是否包含指定的键的效率更高。


    数据结构越大,效率差距就越大。


练习:

people = {
    'Alice':{
        'phone':'1234',
        'add':'Fpp drive 23'
    },
    'Beth': {
        'phone': '1234',
        'add': 'Fpp drive 26'
    },
    'cooper': {
        'phone': '1234',
        'add': 'Fpp drive 30'
    },
}

labels = {
    'phone':'phone number',
    'add':'address',
}
name = input('Enter Name:')
label = input('phone or add (p or a):')

key = ''
if label == 'p':
    key = 'phone'
elif label == 'a':
    key = 'add'

if name in people:
    print("{}'s {} is {}".format(name, labels[key],people[name][key]))
将字符串格式设置功能用于字典

可在字典中包含各种信息,这样只需在格式字符串中提取所需的信息即可。


为此,必须使用format_map来指出你将通过一个映射来提供所需的信息。




通过format_map将字典中的内容映射出来。


字典方法:

clear(),方法clear删除所有的字典项,这种 *** 作是就地执行的(就像list.sort一样),因此什么都不返回(或者说返回None)



对比这两张图,会发现,使用clear方法后,别名也被清空了。


方法copy返回一个新字典,其包含的键-值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本)

这个方法也需要格外注意,copy进行的是浅复制,对嵌套层的修改会影响原件。


如图中,字典里的列表就是嵌套层。


对里面的值进行修改,会影响到原件的内容。


有的时候,为了解决这个问题,可使用模块copy中的函数deepcopy。




方法fromkeys创建一个新字典,其中包含指定的键,且每个键对应的值都是None。




也可以这样,用dict

也可以提供特定的值,

使用get来访问不存在的键时,没有引发异常,而是返回None。


你可指定“默认”值,这样将返回你指定的值而不是None

方法items返回一个包含所有字典项的列表,其中每个元素都为(key, value)的形式。


字典项在列表中的排列顺序不确定。



返回值属于一种名为字典视图的特殊类型。


字典视图可用于迭代(迭代将在第5章详细介绍)。


另外,你还可确定其长度以及对其执行成员资格检查。




方法keys返回一个字典视图,其中包含指定字典中的键。


方法pop可用于获取与指定键相关联的值,并将该键-值对从字典中删除。




popitem随机地d出一个字典项。




方法setdefault有点像get,因为它也获取与指定键相关联的值,但除此之外,setdefault还在字典不包含指定的键时,在字典中添加指定的键-值对。




方法update使用一个字典中的项来更新另一个字典。


对于通过参数提供的字典,将其项添加到当前字典中。


如果当前字典包含键相同的项,就替换它。




方法values返回一个由字典中的值组成的字典视图。


不同于方法keys,方法values返回的视图可能包含重复的值。


  • 完成第四章

第五章

print函数的小技巧:可以添加分隔符sep 和 结束符 end:end默认是\n,换行符。


print('hello','world', sep='_',end='kk')
hello_worldkk

import语句可以给模块和方法指定别名:


序列解包: 将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中

字典方法popitem,随机从字典中获得键值对,并返回一个元组。




可以通过解包的方式获得内容。



注意:要解包的序列包含的元素个数必须与你在等号左边列出的目标个数相同


可使用星号运算符(*)来收集多余的值,这样无需确保值和变量的个数相同

*放在其他位置也一样。




赋值语句的右边可以是任何类型的序列,但带星号的变量最终包含的总是一个列表

IF 语句

用作布尔表达式(如用作if语句中的条件)时,下面的值都将被解释器视为假

if、elif、else。




==是相等运算符,比较的是值相等,is是相同运算符,比较的是id是否一样。


不要将is用于数和字符串等不可变的基本值。


鉴于Python在内部处理这些对象的方式,这样做的结果是不可预测的。


字符串是根据字符的字母排列顺序进行比较的。


再说的直接些,字符是按照顺序值排序的

ord('a')
97
chr(97)
'a'

短路逻辑(或者延迟求值):布尔中 x and y ,x or y , 在and中只要x为假,就立刻返回结果假,在or中,只要x为真,就立刻返回结果为真。


assert 断言。




一个很有用的并行迭代工具是内置函数zip,它将两个序列“缝合”起来,并返回一个由元组组成的序列。


names = ['cooper', 'lili', 'mike']
ages = ['29', '30', '31']
na = zip(names, ages)
na
<zip object at 0x00000187F744E400>
list(na)
[('cooper', '29'), ('lili', '30'), ('mike', '31')]
dict(na)
{}

基于内存的考虑,zip只能访问一次。


函数zip可用于“缝合”任意数量的序列。


需要指出的是,当序列的长度不同时,函数zip将在最短的序列用完后停止“缝合”

内置函数enumerate。




reversed和sorted,可用于任何序列或可迭代的对象,且不就地修改对象,而是返回反转和排序后的版本。




sorted返回一个列表,而reversed像zip那样返回一个更神秘的可迭代对象。


else 可以处理循环正常结束后的内容。



无论是在for循环还是while循环中,都可使用continue、break和else子句。




列表推导,可以有多个for循环。




练习:

girls = ['alice', 'bernice', 'clarice']
boys = ['chris', 'arnold', 'bob']
lettergirls = {}
for girl in girls:
    lettergirls.setdefault(girl[0],[]).append(girl)
    print(lettergirls)
print([b+'+'+g for b in boys for g in lettergirls[b[0]]])

可使用花括号来执行字典推导

在Python中,根本就没有办法删除值,而且你也不需要这样做,因为对于你不再使用的值,Python解释器会立即将其删除。



使用del 语句删除变量,删除的只是变量的名称,它原本的值python会在适当的时候自动删除。


函数exec将字符串作为代码执行

在大多数情况下,还应向它传递一个命名空间——用于放置变量的地方;否则代码将污染你的命名空间,即修改你的变量。




sqrt 已经作为变量存在了。


函数exec主要用于动态地创建代码字符串。


如果这种字符串来自其他地方(可能是用户),就几乎无法确定它将包含什么内容。


因此为了安全起见,要提供一个字典以充当命名空间。



eval是一个类似于exec的内置函数,eval计算用字符串表示的Python表达式的值,并返回结果

  • 完成第五章

第六章

要判断某个对象是否可调用,可使用内置函数callable

class Bt:
    def say(self):
        return 10
    
y = Bt()
callable(y)
False
x = y.say
callable(x)
True

要给函数编写文档,以确保其他人能够理解,可添加注释(以#打头的内容)。


还有另一种编写注释的方式,就是添加独立的字符串。



放在函数开头的字符串称为文档字符串

可以使用doc魔法方法访问。




特殊的内置函数help很有用。


在交互式解释器中,可使用它获取有关函数的信息,其中包含函数的文档字符串

所有的函数都返回值。


如果你没有告诉它们该返回什么,将返回None。


如果参数是不可变的类型,如字符串,数字或者元组,在函数内部给参数赋值对外部没有任何影响

如果参数为可变的数据结构(如列表),在函数内对其进行修改将会对外部产生影响。


对列表进行添加,删减,替换都会影响函数外部。




类似于这样:

练习:

def init(data):
    data['first'] = {}
    data['middle'] = {}
    data['last'] = {}

def lookup(data, label, name):
    return data[label].get(name)

def store(data, full_name):
    names = full_name.split()
    if len(names)==2:
        names.insert(1,'')
    labels = ['first', 'middle', 'last']

    for name, label in zip(names, labels):
        people = lookup(data, label, name)
        if people:
            people.append(full_name)
        else:
            data[label][name] = [full_name]

storage = {}
init(storage)
store(storage, 'jore cooper rich')
print(storage)

你可结合使用位置参数和关键字参数,但必须先指定所有的位置参数,否则解释器将不知道它们是哪个参数

带星号的参数也可放在其他位置(而不是最后),但不同的是,在这种情况下你需要做些额外的工作:使用名称来指定后续参数

要收集关键字参数,可使用两个星号,这样得到的是一个字典而不是元组

太灵活了,还可以分配参数。



如果在定义和调用函数时都使用*或**,将只传递元组或字典。


def internal(start, stop=None, step=1):
    if stop is None:
        start, stop = 0, start

    result = []

    i = start
    while i <stop:
        result.append(i)
        i += step

    return result

print(internal(10,29,2))

变量到底是什么呢?可将其视为指向值的名称。


因此,执行赋值语句x = 1后,名称x指向值1。


这几乎与使用字典时一样(字典中的键指向值),只是你使用的是“看不见”的字典。


实际上,这种解释已经离真相不远。


有一个名为vars的内置函数,它返回这个不可见的字典


变量其实存在一个内置的看不见的字典里。


这种“看不见的字典”称为命名空间或作用域
除全局作用域外,每个函数调用都将创建一个

这个问题就回答清楚了。




在这里,函数foo修改(重新关联)了变量x,但当你最终查看时,它根本没变。


这是因为调用foo时创建了一个新的命名空间,供foo中的代码块使用。


赋值语句x =42是在这个内部作用域(局部命名空间)中执行的,不影响外部(全局)作用域内的x。


在函数内使用的变量称为局部变量(与之相对的是全局变量)。


参数类似于局部变量,因此参数与全局变量同名不会有任何问题。


如果函数内部有参数和外部的同名,可以使用函数globals来访问全局变量。


这个函数类似于vars,返回一个包含全局变量的字典


locals返回一个包含局部变量的字典。


可以在函数内部 使用global 声明变量为全局变量。




存储其所在作用域的函数称为闭包
作用域嵌套

def kk(n):
    def jj(m):
        return m+n
    return jj

x = kk(5)
y = x(7)
print(y)

外层的函数返回的是内层的函数。


递归

基线条件(针对最小的问题):满足这种条件时函数将直接返回一个值。



递归条件:包含一个或多个调用,这些调用旨在解决问题的一部分

通过将问题分解为较小的部分,可避免递归没完没了,因为问题终将被分解成基线条件可以解决的最小问题。


很好的解释了,函数如何调用自身的问题。


函数虽然一样,命名空间却不同。



那么如何让函数调用自身呢?这没有看起来那么难懂。


前面说过,每次调用函数时,都将为此创建一个新的命名空间。


这意味着函数调用自身时,是两个不同的函数[更准确地说,是不同版本(即命名空间不同)的同一个函数]在交流。


你可将此视为两个属于相同物种的动物在彼此交流。


def factorial(n):
    if n==1:
        return 1
    return n * factorial(n-1)

print(factorial(6))
def mi(x,n):  # 2**3
    if n ==1:
        return x
    return x * mi(x,n-1)

print(mi(3,3))
二分查找:
// An highlighted block
var foo = 'bar';

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/571024.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存