python语言print(3)出来为啥2.9999_面试遇到的 python 问题 -- 2019年 爱谱纳纳

1、 sql 语句 连表查询

没答上,不会写,应该用join

设定两张表,学生表student

专业表major

1.1 INNER JOIN 内连接

1.1.1 等值连接

查找两个表中连接字段相等的记录

写法1:使用INNER JOIN

SELECT A.学号,A.姓名,A.籍贯,A.年龄,B.专业,B.班级 FROM student A INNER JOIN major B ON A.学号=B.学号

写法2:–省去了INNER,直接写JOIN,与INNER JOIN没有区别

SELECT A.学号,A.姓名,A.籍贯,A.年龄,B.专业,B.班级 FROM student A JOIN major B ON A.学号=B.学号

写法3: --使用WHERE,已经逐渐被淘汰

SELECT A.学号,A.姓名,A.籍贯,A.年龄,B.专业,B.班级 FROM student A, major B WHERE A.学号=B.学号

上面三种写法的结果都是一样的,推荐使用写法2

1.1.2 自身连接

就是和自己进行连接查询,给一张表取两个不同的别名,然后附上连接条件

要在学生表里查询与 HH 同龄且籍贯也相同的学生信息

SELECT B.学号,B.姓名,B.性别,B.籍贯,B.年龄 FROM student A JOIN student B ON A.年龄=B.年龄 AND A.籍贯=B.籍贯 AND A.姓名=‘HH’

2. LEFT JOIN 左连接

获取左表中的所有记录,即使在右表没有对应匹配的记录

左连接:显示左表student所有记录,如右表中没有与之

匹配的项则以NULL值代替。

SELECT A.学号,A.姓名,A.籍贯,A.年龄,B.专业,B.班级 FROM student A LEFT JOIN major B ON A.学号=B.学号

3.RIGHT JOIN 右连接

用于获取右表中的所有记录,即使左表没有对应匹配的记录。

–右连接:显示右表major所有记录,如左表中没有与之

–匹配的项则以NULL值代替。

SELECT A.学号, A.姓名, A.籍贯, A.年龄, B.专业, B.班级 FROM student A RIGHT JOIN major B ON A.学号=B.学号

4.FULL JOIN 完全连接

返回两个表中的所有行。

–完全连接:显示两张表的并集,如果其中一张表的记录

–在另一张表中没有匹配的行,则对应的数据项填充NULL

SELECT A.学号, A.姓名, A.籍贯, A.年龄, B.专业, B.班级 FROM student A FULL JOIN major B ON A.学号=B.学号

5. CROSS JOIN 交叉连接

结果是笛卡尔积,就是第一个表的行数乘以第二个表的行数。

–交叉连接:一张表中的数据依次取出分别与另一张表中的

–每条数据挨个组合,最后记录数量为两张表记录数的乘积

SELECT * FROM student CROSS JOIN major

–本例student和major都为7条记录,所以结果为7*7=49条记录

6. Left Excluding JOIN 左表唯一

返回左表有但右表没有关联数据的记录。

–左表唯一:将右表B以及两张表交集的部分过滤掉,

–得到的记录是左表中唯一存在的。

SELECT A.学号, A.姓名, A.籍贯, A.年龄, B.专业, B.班级

FROM student A LEFT JOIN major B

ON A.学号=B.学号

WHERE B.学号 IS NULL

7. Right Excluding JOIN 右表唯一

返回右表有但左表没有关联数据的记录。

–右表唯一:将左表A以及两张表交集的部分过滤掉,

–得到的记录是右表中唯一存在的。

SELECT A.学号, A.姓名, A.籍贯, A.年龄, B.专业, B.班级 FROM student A RIGHT JOIN major B ON A.学号=B.学号 WHERE A.学号 IS NULL

8. Outer Excluding JOIN 非交集连接

返回左表和右表里没有相互关联的记录。

–非交集连接:查找两张表中没有关联的记录项。

SELECT A.学号, A.姓名, A.籍贯, A.年龄, B.专业, B.班级 FROM student A FULL JOIN major B ON A.学号=B.学号 WHERE A.学号 IS NULL OR B.学号 IS NULL

2. Django信号都有哪些,如何使用

没答上,没咋用,简历上还说了解django,这都不知道还了解毛线

django的信号机制其实还是相当有用的,记得有次业务需求是要在数据库变动前后添加日志,很多人第一时间想到的是用装饰器,包括我也是,后来想想,其实设置信号就可以早早完事了。

django中的信号也称signal,用于在框架执行操作时解耦。通俗点讲,就是框架发生一些动作之前或之后,可以自动根据我们提前设置好的signal去执行对应函数。熟悉数据库的小伙伴应该知道“触发器”吧?就是类似的功能。

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

2.1 Django内置信号

Model signals: (Model 信号)

pre_init # django的modal执行其构造方法前,自动触发

post_init # django的modal执行其构造方法后,自动触发

pre_save # django的modal对象保存前,自动触发

post_save # django的modal对象保存后,自动触发

pre_delete # django的modal对象删除前,自动触发

post_delete # django的modal对象删除后,自动触发

m2m_changed (m2m指的是manytomany) # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发

class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发

Management signals:(管理信号)

pre_migrate # 执行migrate命令前,自动触发

post_migrate # 执行migrate命令后,自动触发

Request/response signals:(请求返回信号)

request_started # 请求到来前,自动触发

request_finished # 请求结束后,自动触发

got_request_exception # 请求异常后,自动触发

Test signals:(测试信号)

setting_changed # 使用test测试修改配置文件时,自动触发

template_rendered # 使用test测试渲染模板时,自动触发

Database Wrappers:(数据库信号)

connection_created # 创建数据库连接时,自动触发

2.2 怎么用信号

对于内置信号来说,只需要把想执行的函数注册到信号,那么当动作发生时对应的信号函数便会自动执行。这里给两个例子:

2.2.1 全导入:

from django.core.signals import request_finished

from django.core.signals import request_started

from django.core.signals import got_request_exception

from django.db.models.signals import class_prepared

from django.db.models.signals import pre_init, post_init

from django.db.models.signals import pre_save, post_save

from django.db.models.signals import pre_delete, post_delete

from django.db.models.signals import m2m_changed

from django.db.models.signals import pre_migrate, post_migrate

from django.test.signals import setting_changed

from django.test.signals import template_rendered

from django.db.backends.signals import connection_created

def test(sender, **kwargs):

print("it work")

#'sender'包含了这个动作发生时传入的参数

request_finished.connect(test) #需要什么类型的信号,就信号.connect(函数名)

在使用这种方式的时候,建议在项目根目录下创建个新的py文件把信号放进去,然后在项目的init里直接import py文件名,这样views.py就不必再做手脚了。

2.2.2 局部导入:

from django.core.signals import request_finished

from django.dispatch import receiver

@receiver(request_finished)

def my_callback(sender, **kwargs):

print("Request finished!")

这种方法也是在init中修改

2.3 自定义信号

2.3.1 创建信号

想要发送信号,必须先要创建一个信号,在django中,信号是django.dispatch.Signal类的实例,该类的构造函数接受一个名叫providing_args参数,该参数是参数名列表,举例如下:

import django.dispatch

game_start = django.dispatch.Signal(providing_args=['player','level'])

该段代码的意思是,生成一个信号,信号包含两个参数,游戏者,关卡.

2.3.2 指定信号发送者

有了信号,我们要确定信号是谁发送出去的,这个时候就要用到“`Signal.send(sender, **kwargs)方法了.代码示例以及解释如下:

class Game(object):

def start(self,user,level):

game_start.send(sender=self.__class__,player=user,level=level)

2.3.3 信号监听

由于信号接受方不知道信号什么时候会传递过来,所以接收方一般是在做持续监听,收到信号就触发反应,没收到就一直待机.因此我们需要一个负责监听的方法.这个方法是Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)

现在来解释一下最基本的参数:

receiver: 信号接受者,回调函数

sender: 信号发送者

例如

game_start.connect(game_logger)

开启监听之后,就要去实现回调函数了

def game_logger():

# log to log file

print 'Done!'

流程解释

首先我们创建了一个在游戏开始是发出的信号

在游戏开始时让指定的发送者发出信号

接受端一直处于监听状态,收到信号,调用回调函数,将游戏者和关卡信息写入日志

3. python中的猴子补丁是什么,怎么用

3.1 概念和来源

所谓的猴子补丁,是指在运行时修改类或模块,而不去改变源码,达到hot patch的目的

猴补丁(英语:Monkey patch)是一种很脏的编程技巧,用拼凑代码的方法修改程序逻辑。

Monkey patching 只能在动态语言中实现。比如Python类的方法其实也只是一个属性,方便运行时修改,所以用Python做猴子补丁非常方便。

这个词原来为Guerrilla Patch,杂牌军、游击队,说明这部分不是原装的,在英文里guerilla发音和gorllia(猩猩)相似,再后来就写了monkey(猴子)。

还有一种解释是说由于这种方式将原来的代码弄乱了(messing with it),在英文里叫monkeying about(顽皮的),所以叫做Monkey Patch。

3.2 使用方法

利用猴子补丁,动态修改math标准库中Pi的默认值。(这里仅修改了attributes,也可以对某些method进行重写)

>>> import math

>>> math.pi

3.141592653589793

>>> math.pi = 3 # 给标准库打补丁,即运行时修改math的pi属性

>>> math.pi

3

>>> ================================ RESTART ================================

>>> import math

>>> math.pi

3.141592653589793

对方法打补丁

class Foo(object):

def bar(self):

print 'Foo.bar'

def bar(self): # 这是补丁

print 'Modified bar'

Foo().bar()

Foo.bar = bar # 给Foo的bar方法打补丁,即运行时修改类的方法

Foo().bar()

由于Python中的名字空间是开放,通过dict来实现,所以很容易就可以达到patch的目的。

3.3 实际应用案例

3.3.1 Eventlet Patcher

现在我们先来看一下eventlet中的Patcher的调用代码吧,这段代码对标准的ftplib做monkey patch,将eventlet的GreenSocket替换标准的socket。

from eventlet import patcher

# *NOTE: there might be some funny business with the "SOCKS" module

# if it even still exists

from eventlet.green import socket

patcher.inject('ftplib', globals(), ('socket', socket))

del patcher

3.3.2 从Gevent学习猴子补丁的设计

异步协程工具Gevent是python上面最有名也支持面最广通用性最好的协程工具,它底层基于greenlet,而且可以通过使用猴子补丁将标准库中的同步模块自动的转换成异步.同时他也提供了方便的并发模型和常用的web服务器工具.

gevent能够 修改标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和 select等模块,而变为协作式运行。

用过gevent就会知道,会在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.这样我们在后面使用socket的时候可以跟平常一样使用,无需修改任何代码,但是它变成非阻塞的了.

>>> import socket

>>> print(socket.socket) # monkey patch前

>>>

>>> from gevent import monkey # monkey patch后

>>> monkey.patch_socket()

>>> print(socket.socket)

# 改变了标准socket库

>>> import select # monkey patch前

>>> print(select.select) # select()轮询的阻塞调用

>>>

>>> monkey.patch_select() # monkey patch后

>>> print(select.select) # select()轮询的异步调用

例如,Redis的python绑定一般使用常规的tcp socket来与redis-server实例通信。

通过简单地调用gevent.monkey.patch_all(),可以使得redis的绑定协作式的调度 请求,与gevent栈的其它部分一起工作。

除了socket外,gevent还可以为其他的模块打补丁,一起打补丁可以使用

patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, httplib=False,subprocess=True, sys=False, aggressive=True, Event=False, builtins=True, signal=True)

我们可以看到像socket,dns,time,selectthread,os, ssl, httplib,subprocess, sys, aggressive, Event, builtins, signal模块都可以打上补丁,打上以后,他们就是非阻塞的了.

核心协程模块greenlet

import gevent

def foo():

print('Running in foo')

gevent.sleep(0) # 这行的作用是什么?

print('Explicit context switch to foo again')

def bar():

print('Explicit context to bar')

gevent.sleep(0) #

print('Implicit context switch back to bar')

gevent.joinall([

gevent.spawn(foo),

gevent.spawn(bar),

])

输出

Running in foo

Explicit context to bar

Explicit context switch to foo again

Implicit context switch back to bar

[, ]

上述例子能看到,执行顺序是 foo–>bar–foo–bar,来回切换。即gevent.sleep()并不会真正的阻塞整个线程,而是将cpu的控制权显式的交给未被gevent.sleep()阻塞的协程使用。

协程是单线程程序(从上述例子来讲),如果我们使用time.sleep(),那么整个线程都会被阻塞。

gevent.sleep与time.sleep的区别

gevent is a cooperative analog to the threading module. When using gevent.sleep it you would never use time.sleep. So no example is needed.

time.sleep would suspend the entire process, blocking all greenlet threads. 来源。 以上说法针对的是协程(单线程程序)。而对于多线程,time.sleep仅仅阻塞当前线程,不阻塞其他线程

4. python3和2的区别

4.1 print

2中是语句,3中是函数

4.2 编码

2默认ascii,3默认UTF-8编码,以后不用文件开头写#coding=utf-8

4.3 字符串

2中字符串有两种,分别是unicode(表示文本字符串)和str(字节序列),很混乱,容易编码错误

3中字符串,str表示字符串,byte表示字节序列,任何需要写入文本或者网络传输的数据都只接收byte字节序列,这就从源头上阻止了编码错误的问题。

4.4 True和False

True 和 False 在 Python2 中是两个全局变量(名字),在数值上分别对应 1 和 0,既然是变量,那么他们就可以指向其它对象,例如:

# py2

>>> True = False

>>> True

False

>>> True is False

True

>>> False = "x"

>>> False

'x'

>>> if False:

... print("?")

...

?

显然,上面的代码违背了 Python 的设计哲学 Explicit is better than implicit.。而 Python3 修正了这个缺陷,True 和 False 变为两个关键字,永远指向两个固定的对象,不允许再被重新赋值。

# py3

>>> True = 1

File "", line 1

SyntaxError: can't assign to keyword

4.5 迭代器

在 Python2 中很多返回列表对象的内置函数和方法在 Python 3 都改成了返回类似于迭代器的对象,因为迭代器的惰性加载特性使得操作大数据更有效率。Python2 中的 range 和 xrange 函数合并成了 range,字典对象的 dict.keys()、dict.values() 方法都不再返回列表,而是以一个类似迭代器的 “view” 对象返回。高阶函数 map、filter、zip 返回的也都不是列表对象

4.6 nonlocal

我们都知道在Python2中可以在函数里面可以用关键字 global 声明某个变量为全局变量,但是在嵌套函数中,想要给一个变量声明为非局部变量是没法实现的,在Pyhon3,新增了关键字 nonlcoal,使得非局部变量成为可能。

def func():

c = 1

def foo():

c = 12

foo()

print(c)

func() #1

可以对比上面两段代码的输出结果

def func():

c = 1

def foo():

nonlocal c

c = 12

foo()

print(c)

func() # 12

5. http和https区别

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

5.1 HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

5.2 HTTPS的工作原理

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。

HTTP与HTTPS的区别-马海祥博客

客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。

(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。

(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。

(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。

(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。

(5)Web服务器利用自己的私钥解密出会话密钥。

(6)Web服务器利用会话密钥加密与客户端之间的通信。

6.新浪短链接服务如何设计,缩短url,用什么hash算法,后端索引如何设计

现在招聘面试题里面必考的一道,这一道题里面有很多可考的地方,能够相对综合的考察候选人的功力。

最烂的回答 实现一个算法,将长地址转成短地址。实现长和短一一对应。然后再实现它的逆运算,将短地址还能换算回长地址。 这个回答看起来挺完美的,然后候选人也会说现在时间比较短,如果给我时间我去找这个算法就解决问题了。但是稍微有点计算机或者信息论常识的人就能发现,这个算法就跟永动机一样,是永远不可能找到的。即使我们定义短地址是100位。那么它的变化是62的100次方。62=10数字+26大写字母+26小写字母。无论这个数多么大,他也不可能大过世界上可能存在的长地址。所以实现一一对应,本身就是不可能的。 再换一个说法来反驳,如果真有这么一个算法和逆运算,那么基本上现在的压缩软件都可以歇菜了,而世界上所有的信息,都可以压缩到100个字符。这~可能吗。

另一个很烂的回答 和上面一样,也找一个算法,把长地址转成短地址,但是不存在逆运算。我们需要把短对长的关系存到DB中,在通过短查长时,需要查DB。 怎么说呢,没有改变本质,如果真有这么一个算法,那必然是会出现碰撞的,也就是多个长地址转成了同一个短地址。因为我们无法预知会输入什么样的长地址到这个系统中,所以不可能实现这样一个绝对不碰撞的hash函数。

比较烂的回答 那我们用一个hash算法,我承认它会碰撞,碰撞后我再在后面加1,2,3不就行了。 ok,这样的话,当通过这个hash算法算出来之后,可能我们会需要做btree式的大于小于或者like查找到能知道现在应该在后面加1,2,或3,这个也可能由于输入的长地址集的不确定性。导致生成短地址时间的不确定性。同样烂的回答还有随机生成一个短地址,去查找是否用过,用过就再随机,如此往复,直到随机到一个没用过的短地址。

正确的原理 上面是几种典型的错误回答,下面咱们直接说正确的原理。 正确的原理就是通过发号策略,给每一个过来的长地址,发一个号即可,小型系统直接用mysql的自增索引就搞定了。如果是大型应用,可以考虑各种分布式key-value系统做发号器。不停的自增就行了。第一个使用这个服务的人得到的短地址是http://xx.xx/0 第二个是 http://xx.xx/1 第11个是 http://xx.xx/a 第依次往后,相当于实现了一个62进制的自增字段即可。

几个子问题

62进制如何用数据库或者KV存储来做? 其实我们并不需要在存储中用62进制,用10进制就好了。比如第10000个长地址,我们给它的短地址对应的编号是9999,我们通过存储自增拿到9999后,再做一个10进制到62进制的转换,转成62进制数即可。这个10~62进制转换,你完全都可以自己实现。

如何保证同一个长地址,每次转出来都是一样的短地址 上面的发号原理中,是不判断长地址是否已经转过的。也就是说用拿着百度首页地址来转,我给一个http://xx.xx/abc 过一段时间你再来转,我还会给你一个 http://xx.xx/xyz。这看起来挺不好的,但是不好在哪里呢?不好在不是一一对应,而一长对多短。这与我们完美主义的基因不符合,那么除此以外还有什么不对的地方? 有人说它浪费空间,这是对的。同一个长地址,产生多条短地址记录,这明显是浪费空间的。那么我们如何避免空间浪费,有人非常迅速的回答我,建立一个长对短的KV存储即可。嗯,听起来有理,但是。。。这个KV存储本身就是浪费大量空间。所以我们是在用空间换空间,而且貌似是在用大空间换小空间。真的划算吗?这个问题要考虑一下。当然,也不是没有办法解决,我们做不到真正的一一对应,那么打个折扣是不是可以搞定?这个问题的答案太多种,各有各招,我这就不说了。(由于实在太多人纠结这个问题,请见我最下方的更新)

如何保证发号器的大并发高可用 上面设计看起来有一个单点,那就是发号器。如果做成分布式的,那么多节点要保持同步加1,多点同时写入,这个嘛,以CAP理论看,是不可能真正做到的。其实这个问题的解决非常简单,我们可以退一步考虑,我们是否可以实现两个发号器,一个发单号,一个发双号,这样就变单点为多点了?依次类推,我们可以实现1000个逻辑发号器,分别发尾号为0到999的号。每发一个号,每个发号器加1000,而不是加1。这些发号器独立工作,互不干扰即可。而且在实现上,也可以先是逻辑的,真的压力变大了,再拆分成独立的物理机器单元。1000个节点,估计对人类来说应该够用了。如果你真的还想更多,理论上也是可以的。

具体存储如何选择 这个问题就不展开说了,各有各道,主要考察一下对存储的理解。对缓存原理的理解,和对市面上DB、Cache系统可用性,并发能力,一致性等方面的理解。

跳转用301还是302 这也是一个有意思的话题。首先当然考察一个候选人对301和302的理解。浏览器缓存机制的理解。然后是考察他的业务经验。301是永久重定向,302是临时重定向。短地址一经生成就不会变化,所以用301是符合http语义的。同时对服务器压力也会有一定减少。 但是如果使用了301,我们就无法统计到短地址被点击的次数了。而这个点击次数是一个非常有意思的大数据分析数据源。能够分析出的东西非常非常多。所以选择302虽然会增加服务器压力,但是我想是一个更好的选择。

大概就是这样。

如何实现同一个长地址多次转换,出来还是同一个短地址。

我上面其实讲到了,这个方案最简单的是建立一个长对短的hashtable,这样相当于用空间来换空间,同时换取一个设计上的优雅(真正的一对一)。

实际情况是有很多性价比高的打折方案可以用,这个方案设计因人而异了。那我就说一下我的方案吧。

我的方案是:用key-value存储,保存“最近”生成的长对短的一个对应关系。注意是“最近”,也就是说,我并不保存全量的长对短的关系,而只保存最近的。比如采用一小时过期的机制来实现LRU淘汰。

这样的话,长转短的流程变成这样: 1 在这个“最近”表中查看一下,看长地址有没有对应的短地址 1.1 有就直接返回,并且将这个key-value对的过期时间再延长成一小时 1.2 如果没有,就通过发号器生成一个短地址,并且将这个“最近”表中,过期时间为1小时

所以当一个地址被频繁使用,那么它会一直在这个key-value表中,总能返回当初生成那个短地址,不会出现重复的问题。如果它使用并不频繁,那么长对短的key会过期,LRU机制自动就会淘汰掉它。

当然,这不能保证100%的同一个长地址一定能转出同一个短地址,比如你拿一个生僻的url,每间隔1小时来转一次,你会得到不同的短地址。但是这真的有关系吗?

7.decimal模块如何进行浮点数计算?

7.1 简介

如果你从事科学或工程领域的大多数计算,那么使用普通的浮点类型是比较普遍的做法。因为在真实世界中很少会要求精确到17位精度的普通浮点数。因此,计算过程中的那么一点点的误差是被允许的。其次,原生的二进制浮点数计算要快的多-有时候你在执行大量运算的时候速度也是非常重要的。总的来说,decimal 模块主要用在涉及到金融的领域。在这类程序中,哪怕是一点小小的误差在计算过程中蔓延都是不允许的。因此,decimal 模块为解决这类精度问题提供了方法。decimal意思为十进制,这个模块提供了十进制浮点运算支持。我们在数据库处理金融数据的时候也会遇到 Decimal 对象。

7.2 问题

当你在编写科学计算或者金融程序的时候碰到这种情况会让人发狂:

>>>a = 4.2

>>>b = 2.1

>>>a + b

6.300000000000001

这就是机器进行二进制计算引入的误差,为了消除这样的误差,进行更加精确的浮点计算,就要是用到decimal模块。

7.3 Decimal()函数

from decimal import *

我们直接导入decimal模块里的所有函数。现在我们可以通过Decimal函数构建十进制浮点数,并进行常规的数值计算。

>>>a = Decimal('4.2')

>>>b = Decimal('2.1')

>>>a + b

Decimal('6.3')

>>>x = Decimal(3)

>>>y = Decimal(1)

>>>x + y

Decimal('4')

注意,Decimal函数传入的浮点数必须加引号(”),表示成字符串形式。传入整数时就不用加。Decimal函数的对象类型是decimal.Decimal,可以通过type()函数查看。

7.4 浮点数据转换成Decimal

Decimal函数并不建议传入浮点型数据,因为浮点型数据本身就是不精确的。可以通过两种方式传入浮点型数据:

>>>Decimal(1.22)

Decimal('1.2199999999999999733546474089962430298328399658203125')

>>>Decimal.from_float(15.3333)

Decimal('15.3332999999999994855670593096874654293060302734375')

7.5 getcontext().prec 设定有效数字

>>>getcontext().prec = 4

>>>Decimal('2.2') / Decimal('1.3')

Decimal('1.692')

保留4位有效数字。

7.6 设定小数位数

>>>Decimal('1.2346568355').quantize(Decimal('0.00'))

Decimal('1.23')

7.7 转为字符串,浮点数

直接调用str(),float()函数:

>>>str(Decimal('1.2346568355').quantize(Decimal('0.00')))

'1.23'

>>>float(Decimal('1.2346568355').quantize(Decimal('0.00')))

1.23

8.Django中url和path区别

8.1 引用路径的区别:

1.X: 使用的是django.conf.urls.url, django.conf.urls.include

2.X: 使用的是django.urls.path, django.urls.include, django.urls.re_path

8.2 引入正则的区别:

1.X:

下面的示例使用简单的正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式传递给视图

在更高级的用法中,可以使用分组命名匹配的正则表达式组来捕获URL中的值并以关键字参数形式传递给视图。

在Python的正则表达式中,分组命名正则表达式组的语法是(?Ppattern),其中name是组的名称,pattern是要匹配的模式。

urlpatterns = [

url('index-(\d+)-(\d+).html',views.index),

url('index-(?P\d+)-(?P\d+).html',views.index)

]

#url请求地址为:http://127.0.0.1:8000/index-1-1.html

2.X:

基本规则:

使用尖括号(<>)从url中捕获值。

捕获值中可以包含一个转化器类型(converter type),比如使用 int:name 捕获一个整数变量。若果没 有转化器,将匹配任何字符串,当然也包括了 / 字符。

无需添加前导斜杠。

urlpatterns = [

path('index--.html',views.index),

]

#url请求地址为:http://127.0.0.1:8000/index-1-1.html

在Python正则表达式中,命名式分组语法为 (?Ppattern) ,其中name为名称, pattern为待匹配的模式。这个与1.X的用法差不多,就是将1.X的url,改为re_path,

例子:

urlpatterns = [

path('articles/2003/', views.special_case_2003),

re_path('articles/(?P[0-9]{4})/', views.year_archive),

re_path('articles/(?P[0-9]{4})/(?P[0-9]{2})/', views.month_archive),

re_path('articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[^/]+)/', views.article_detail),

]

9.一个list,一边迭代一边处理行不行

不要这么搞,容易引入未知风险

标签:爱谱,JOIN,学号,纳纳,Decimal,django,python,地址,import

来源: https://blog.csdn.net/u013205877/article/details/97005805

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值