搞定三大神器之 Python 装饰器

来自公众号:Python与算法社区

学会 Python 装饰器

装饰器,几乎各大Python框架中都能看到它的身影,足以表明它的价值!它有动态改变函数或类功能的魔力!

本专题的目录:

  • 学会 Python 装饰器
    • 1 什么是装饰器
    • 2 装饰器的结构
    • 3 为什么要这样
    • 4 装饰一个函数
    • 5 装饰一个类
    • 6 装饰器层叠
    • 7 温馨提醒
    • 总结

1 什么是装饰器

对于受到封装的原函数比如f来说,装饰器能够在f函数执行前或者执行后分别运行一些代码。

2 装饰器的结构

装饰器也是一个函数,它装饰原函数f或类cls后,再返回一个函数g

装饰一个函数:

def decorator(f):
  # 定义要返回的函数
  def g():
    print('函数f执行前的动作')
    f()
    print('函数f执行后的动作')
  return g

装饰一个类:

def decorator(cls):
  # 定义要返回的函数
  def g():
    print('类cls执行前的动作')
    f()
    print('类cls执行后的动作')
  return g

使用装饰器很简单,@+自定义装饰器 装饰要想装饰的函数。

3 为什么要这样

要想理解装饰器为什么要有这种结构,要首先想明白装饰器的目标是什么。

它的价值在于为原函数f增加一些行为,前提必须不能破坏函数f,所以肯定不能改变f的内部结构,所以只能在调用f前后定义一些行为。

同时,装饰器函数decorator返回值又是什么?你可以思考下,返回一个函数是再好不过的了,它包装了原函数f.

4 装饰一个函数

printStar函数接收一个函数f,返回值也是一个函数,所以满足装饰器的结构要求,所以printStar是一个装饰器。

def printStar(f):
    def g():
        print('*'*20)
        f()
        print('*'*20)
    return g

printStar装饰器实现f函数执行前、后各打印20个*字符。

使用printStar:

@printStar
def f():
    print('hello world')

调用:

if __name__ == '__main__':
   ### 改变函数功能
   f()

打印结果:

********************
hello world
********************

可以很方便的装饰要想装饰的其他函数,如下:

@printStar
def g():
    print('welcome to Python')

5 装饰一个类

除了可以装饰函数f外,还可以装饰类cls,两者原理都是一样的。

下面给出一个装饰器实现单例模式的例子,所谓单例就是类只有唯一实例,不能有第二个。

def singleton(cls):
   instance = {}

   def get_instance(*args, **kwargs):
       if cls not in instance:
           instance[cls] = cls(*args, **kwargs)
       return instance[cls]
   return get_instance

定义字典instance,键值对分别为类和实例,这样确保只cls()一次。

使用装饰器singleton修饰类:

@singleton
class CorePoint:
   pass

测试:

if __name__ == '__main__':
   ### 改变类的功能
   c1 = CorePoint()
   c2 = CorePoint()
   print(c1 is c2) # True

6 装饰器层叠

上面原函数f不仅能被一个装饰器修饰,还能被n多个装饰器修饰。

下面再定义一个装饰器printLine,被修饰函数执行前后打印20个 –

def printLine(f):
    def g():
        print('-'*20)
        f()
        print('-'*20)
    return g

使用上文定义好的printStarprintLine同时装饰函数f:

@printStar
@printLine
def f():
    print('hello world')

此时再调用函数f:

if __name__ == '__main__':
   ### 改变函数功能
   f()

打印结果:

********************
--------------------
hello world
--------------------
********************

f被装饰后,先打印*,再打印 –

层叠多一层,原函数f就变强大一层。使用装饰器,还能实现功能抽离,进一步实现松耦合。

7 温馨提醒

打印原函数f的名字__name__,结果为f

In [1]: def f(): 
   ...:     pass 

In [4]: f.__name__                                                              
Out[4]: 'f'

但是,被装饰后函数名字f变为g,这不是我们希望的!

@printStar
def f():
  pass

f()
f.__name__ # g

Python提供的解决方案:使用functools模块中的wraps装饰器:

from functools import wraps

def printStar(f):
    @wraps(f)
    def g():
        print('*'*20)
        f()
        print('*'*20)
    return g

此时再打印被装饰后f的名字,显示f,正常!

总结

  • 学会 Python 装饰器
    • 1 什么是装饰器
    • 2 装饰器的结构
    • 3 为什么要这样
    • 4 装饰一个函数
    • 5 装饰一个类
    • 6 装饰器层叠
    • 7 温馨提醒
    • 总结

以上就是装饰器的核心使用逻辑专题,希望能帮助到各位读者,若觉得有用,欢迎三连支持。咱们下个专题再见!

Python 之父为什么嫌弃 lambda 匿名函数?

👆 Python猫” ,一个值得加星标的公众号
Python 之父为什么嫌弃 lambda 匿名函数?

Python 支持 lambda 匿名函数,其扩展的 BNF 表示法是lambda_expr ::= "lambda" [parameter_list] ":" expression,也就是lambda 参数序列:表达式

这是一种便捷的函数定义方式,若翻译成我们熟知的函数形式,会是这个样子:

def <lambda>(parameter_list):
    return expression

也就是说,Python 中的 lambda 函数是一种可接收多个参数的函数,返回值是一个表达式。

它最大的好处是单行简洁,不需要函数命名与换行缩进。

不得不说,匿名函数有时候是挺好用的,比如下文会介绍到的一些常见用法,它因此受到了不少人的推崇。

但是,匿名函数通常也会造成代码难以阅读,容易被人滥用,再加上 Python 只提供了对它的“残疾的”支持,所以又有一些观点不建议使用匿名函数。

事实上,Python 之父 Guido van Rossum 就属于“不推荐使用派”,他甚至曾经(2005年)想要移除 lambda,只不过最后妥协了。

Python 之父为什么嫌弃 lambda 匿名函数?
出处:https://www.artima.com/weblogs/viewpost.jsp?thread=98196

lambda 这一个由其他开发者贡献进来的特性(借鉴自 lisp 语言),存在了十多年,但是却被这门语言的创造者(兼首席设计师)所嫌弃,最后竟然还奇迹般地幸存了下来,对于这个故事,大家是否觉得挺有戏剧性的?

接下来,本文就仔细聊一聊这个处境尴尬却生命力顽强的 lambda 匿名函数吧!

1、lambda 怎么使用?

lambda 函数通常的用法是结合 map()、reduce()、filter()、sorted() 等函数一起使用,这些函数的共性是:都可以接收其它函数作为参数。

例如下面的几个例子:

my_list = [315410]

# 元素全加1,结果:[4, 2, 6, 5, 11]
list(map(lambda i:i+1, my_list)) 

# 过滤小于10的元素,结果:[3, 1, 5, 4]
list(filter(lambda i:i<10, my_list)) 

# 元素累加,结果:33
from functools import reduce
reduce(lambda i,j:i+j, my_list, 10)

# 字典按值排序,结果:[('b', 1), ('a', 3), ('d', 4), ('c', 5)]
my_dict = {'a':3'b':1'c':5'd':4}
sorted(my_dict.items(), key=lambda item:item[1])

初学者也许会觉得代码读不懂,但是只要记住“Python中的函数是一等公民”,知道一个函数可以被作为另一个函数的参数或者返回值,就容易理解了。

比如对于 map() 函数的例子,你可以理解成这个形式:

my_func = lambda i:i+1
list(map(my_func, my_list)) 

甚至可以还原成普通的函数:

def add_one(i):
    return i+1

list(map(add_one, my_list)) 

map() 函数的第一个参数是一个函数,第二个参数是一个可迭代对象。这第一个参数会迭代地调用第二个参数中的元素,调用的结果以迭代器的形式返回。

这个例子使用了 list(),是为了方便一次性取出迭代器中的元素,直观地展示出来,在实际使用中,很可能会是基于迭代器的形式。

由这几种用法,我们可以总结出 lambda 函数的使用规律:
  • 它出现在需要使用函数的地方
  • 它适合实现简单的功能
  • 它是一次性的用途,不能在其它地方复用
  • 它一般不会被独立使用,总是作为其它函数的一部分

2、lambda 有什么问题?

由上面的用法可以看出,使用 lambda 函数的代码比较紧凑简洁,所以有人称它体现了“Pythonic”的优雅思想。

但是,lambda 函数有没有什么缺陷呢?

有!当前的 lambda 函数有一个最大的问题,即只支持单行表达式,无法实现丰富的功能,例如无法在函数创建时使用语句(statement),无法使用 if-else 的判断条件,也无法使用 try-except 的异常捕获机制,等等。

这极大地限制了它的能力,导致了它被人诟病为“残疾的”。

从技术实现的角度上看, 这个问题可以通过语法层面的设计来解决。

在当年的邮件组讨论中,有人提出过一些解决思路,比如这封邮件:

Python 之父为什么嫌弃 lambda 匿名函数?
出处:https://mail.python.org/pipermail/python-dev/2006-February/060654.html

它提出了一个lambda args::suite 的想法,支持写成这样的形式:

ss = sorted(seq, key=(lambda x::
            tryreturn abs(x)
            except TypeError: return 0))

但是,Guido 很快就否决了这个思路。

他写了一篇文章《Language Design Is Not Just Solving Puzzles》来回应:

Python 之父为什么嫌弃 lambda 匿名函数?
出处:https://www.artima.com/weblogs/viewpost.jsp?thread=147358

其基本观点是:不能光顾着解决一个问题/实现某种功能,就引入缺乏“Pythonicity”的语言设计。

那么,为什么 Guido 会认为这是一种不好的设计呢?

我试着概括一下,理由是:
  • 双冒号“::”凭空在此引入,但是跟切片语法中的“::”完全不同,而且跟 C++/Perl 中的作用域操作符用法也不同

  • 即使不用双冒号,用其它符号表示(比如单冒号),还是难以接受,因为都会在一个表达式中嵌入缩进代码块。这就跟使用花括号和 begin/end 关键字来作语句分组(statement grouping)一样,都令人难以接受

  • 在 lambda 中实现其它功能并不重要,这还会让解析器变得复杂(需区分是否有缩进、记录缩进级别),显得小题大做了

简而言之,他认为简洁友好的用户体验更为重要,如果简洁的语法无法满足需求,就应该写成具名函数的形式,而非设计出复杂的匿名函数。

3、为什么 Guido 想移除 lambda?

上文提到的多行 lambda 语句(multi-statement lambda)事件发生在 2006 年,我们看到了 Guido 不想给 lambda 引入复杂设计的原因。

但是,早在 2005 年,Guido 就曾经想要从 Python 移除 lambda,他对它的“嫌弃”是一个“历史悠久”的传统……

在《The fate of reduce() in Python 3000》这篇短文中,Guido 提出要一次性移除 reduce()、map()、filter() 以及 lambda。

移除 lambda 的理由如下:
  • 对于不熟悉 Lisp 或 Scheme 的用户,lambda 这名字容易造成混淆

  • 很多人误以为匿名函数能做嵌套函数不能做的事,但其实并无区别;存在lambda,就会造成不必要的选择,减少选择,可以简化思维

  • 移除 reduce()、map() 和 filter() 后,就没必要写简短的局部函数了

回顾一下我们在前文中总结出的 lambda 的 4 条使用规律,可以发现它跟几个高阶函数(可以接收其它函数作为参数的函数)有较强的“寄生关系”,如果它们能移除了的话,lambda 确实就没有什么独立存留的意义了。

那么,为什么 Guido 觉得应该移除那几个高阶函数呢?

主要的理由有:
  • 可以替换成更加清晰的列表解析式或者生成器表达式,例如 filter(P,S) 可以写成 [x for x in S if P(x)],map(F, S) 写成 [F(x) for x in S]

  • 至于 reduce(),他说这是最讨厌的,除了涉及 + 和 * 的少数用法,其它时候他总要拿出纸笔来画图解才能搞清楚。除了显式地写循环,他还针对 reduce() 的几种用法而提出了几个替代用法,包括引入新的 any() 和 all() 函数

总体而言,Guido 的想法暗合了《The Zen of Python》中的这一条:There should be one– and preferably only one –obvious way to do it。

但是回到现实,为了照顾某些人的习惯,以及对兼容性的考虑,Guido 最后保守地放弃了“清理异端”的计划。

因此,lambda 得以从 Python 最高独裁者的手上死里逃生。直到一年后,它试图兴风作浪(多行表达式),却惨遭镇压。

我仿佛听到了 Guido 的内心 OS:当初我想删除东西的时候,你们百般阻挠,现在你们想添加东西,哼,没门!……

Python 之父为什么嫌弃 lambda 匿名函数?

哈哈,开了个玩笑。

Guido 的所有决定都体现了他的 Pythonic 设计美学、自恰的逻辑一致性以及对社区声音的权衡。

对于 lambda,我认可他的观点,而通过回溯语法发展的历史,我觉得自己对于 Python 的理解变得更为丰富了。不知道你可有同感?

 

最后,附上几篇 Python 程序设计相关的文章作为延伸阅读:
1、len(x) 击败 x.len(),从内置函数看 Python 的设计思想
2、编程语言之问:何时该借用,何时该创造?
3、Python 为什么要保留显式的 self ?

4、Python 为什么使用缩进来划分代码块?

Python 之父为什么嫌弃 lambda 匿名函数?

转自: https://mp.weixin.qq.com/s/gEydiMaiknQNgE9Ub9iTPg

Python开源 BI 工具 Superset 的搭建与初级使用

Python开源 BI 工具 Superset 的搭建与初级使用

Superset 是一款由 Airbnb 开源的“现代化的企业级 BI(商业智能) Web 应用程序”,其通过创建和分享 dashboard(看板),为数据分析提供了轻量级的数据查询与可视化方案。

06

目录:
  • 1.搭建流程

    • 1.1.构建虚拟环境

    • 1.2.激活虚拟环境

    • 1.3.安装superset

    • 1.4.初始化superset

    • 1.5.superset启动脚本

  • 2.使用流程

    • 2.1.数据源设置

    • 2.2.上传csv文件

    • 2.3.图表

    • 2.4.看板

官方网站:http://superset.apache.org/
Python开源 BI 工具 Superset 的搭建与初级使用
Superset 是一款由 Airbnb 开源的“现代化的企业级 BI(商业智能) Web 应用程序”,其通过创建和分享 dashboard(看板),为数据分析提供了轻量级的数据查询与可视化方案。
主要功能及特点
(为啥是英文的,因为我不知道怎么翻译的好,反正能看懂就行)
Python开源 BI 工具 Superset 的搭建与初级使用
主要功能
官方看板示例

Python开源 BI 工具 Superset 的搭建与初级使用

1.搭建流程

我的本机环境如下:
# 系统版本:Windows10家庭版
# Python:python 3.7.7
# Superset:0.36.0

1.1.构建虚拟环境

当然,不构建虚拟环境也是可以搭建的,这里构建虚拟环境可以相对保证咱们只需要用到Superset的依赖库,纯净。这里我们简单介绍2中构建虚拟环境的方式,其中一种是通过Anconada navigator直接创建,另外一种是在命令行通过命令创建,大家可以根据自己的实际情况进行选择尝试。
方式一 Anconada navigator
如果你是安装的Anconada,可以直接打开 Anconada navigator,通过以下示例图方式创建虚拟环境supersetTest (名字可以自定义)

Python开源 BI 工具 Superset 的搭建与初级使用

方式二 命令行
如果你安装的是Anconada,通过以下命令即可创建一个名为“supersetTest”的虚拟环境。
conda create -n supersetTest python=3.7.7

Python开源 BI 工具 Superset 的搭建与初级使用

如果是直接安装的python官方环境,可以先安装一个用于创建虚拟环境的第三方库virtualenv,然后再进行虚拟环境构建。
# 安装第三方库
pip install virtualenv
# 创建一个名为supersetTest且不拷贝系统的python第三方库的虚拟环境
virtualenv –no-site-packages supersetTest
# 激活该虚拟环境
supersetTestScriptsactivate.bat
# 退出该虚拟环境
supersetTestScriptsdeactivate.bat

1.2.激活虚拟环境

通过上述方式一,我们构建了虚拟环境 supersetTest,由于安装superset关联的第三方库较多,我们激活该虚拟环境后再进行superset的安装。
# 激活虚拟环境,后续在该环境下安装相关库
activate supersetTest

1.3.安装superset

在之前就行安装的时候,遇到很多问题,当然最后都解决了,所以这里直接以最终解决后总结的安装步骤进行介绍(注意:需要安装在上一步构建的虚拟环境中)。
第一步:升级setuptools和pip;
# Put all the chances on your side by getting the very latest pip and setuptools libraries.:
pip install –upgrade setuptools pip
第二步本地安装以下两个库;
python_geohash-0.8.5-cp37-cp37m-win_amd64.whl
sasl-0.2.1-cp37-cp37m-win_amd64.whl
https://www.lfd.uci.edu/~gohlke/pythonlibs进行以上两个轮子的下载(大家根据自己的环境进行版本选择),然后本地安装,安装过程中一定要注意 被安装文件路径写全。
pip install C:UsersGdcDownloadssasl-0.2.1-cp37-cp37m-win_amd64.whl
pip install C:UsersGdcDownloadspython_geohash-0.8.5-cp37-cp37m-win_amd64.whl
Python开源 BI 工具 Superset 的搭建与初级使用
第三步:安装superset。
完成第一步的安装后,再进行本步骤,一般是很可以很顺利完成安装的,否则可能会出现很多报错(基本都是依赖关系库版本匹配问题等)
pip install apache-superset==0.36.0

1.4.初始化superset

直接拷贝官网初始化流程如下:
# Initialize the database
superset db upgrade

# Create an admin user (you will be prompted to set a username, first and last name before setting a password)
 
nbsp;export FLASK_APP=superset
superset fab create-admin

# Load some data to play with
superset load_examples

# Create default roles and permissions
superset init

# To start a development web server on port 8088, use -p to bind to another port
superset run -p 8088 –with-threads –reload –debugger
不过,这些命令需要在superset安装路径下使用,比如我的是这样:
C:UsersGdcanaconda3envssupersetTestLibsite-packagessupersetbin
按照流程进行执行即可,每一步之前记得加上 python,部分步骤如:
python superset db upgrade【数据库初始化】
Python开源 BI 工具 Superset 的搭建与初级使用
初始化数据库
python superset fab create-admin【创建账号】
Python开源 BI 工具 Superset 的搭建与初级使用

 

创建账号
python superset run -p 8088 –with-threads –reload –debugger【启动superset】
Python开源 BI 工具 Superset 的搭建与初级使用

 

启动superset

1.5.superset启动脚本

为了快捷启动superset,我们可以编写简单的脚本bat文件
call cd C:UsersGdcanaconda3envssupersetTestLibsite-packagessupersetbin
call activate supersetTest
call python superset run -p 8088 –with-threads –reload –debugger

pause

2.使用流程

当我们启动superset之后,在按照提示在浏览器输入“http://127.0.0.1:8088/”即可进行访问,在右侧可以选择页面语言(我这里选择的是中文)。
Python开源 BI 工具 Superset 的搭建与初级使用

 

superset

2.1.数据源设置

数据源设置里我们可以设置数据库,superset支持很多数据库,具体大家在官网即可查阅。这里我使用的是mysql,因此可以在数据源中新增mysql数据源,参考如下:
mysql://root:password@localhost/databasename?charset=utf8
Python开源 BI 工具 Superset 的搭建与初级使用

 

添加数据库

2.2.上传csv文件

除了直接从数据库获取数据外,如果源数据是csv文件,也可以通过上传csv文件(其实是写入了你关联的数据库里)
Python开源 BI 工具 Superset 的搭建与初级使用

 

上传csv文件

2.3.图表

提供很多可视化图表,大家可以根据自己的需求进行数据字段的拖拽,然后创建需要的图表形式。
Python开源 BI 工具 Superset 的搭建与初级使用

 

图表

2.4.看板

多个图表可以组成看板,看板页面也可以自己拖拽图表创建你喜欢的看板形式。
Python开源 BI 工具 Superset 的搭建与初级使用

转自:https://mp.weixin.qq.com/s/3ognn2Q-RG5SCd1VD4MbBA

建议你吃透 Python 的 68 个内置函数!

作者:pypypypy| 来源:博客园

 

内置函数就是Python给你提供的, 拿来直接用的函数,比如print,input等。

截止到python版本3.6.2 ,一共提供了68个内置函数,具体如下👇

abs()           dict()        help()         min()         setattr()
all()           dir()         hex()          next()        slice() 
any()           divmod()      id()           object()      sorted() 
ascii()         enumerate()   input()        oct()         staticmethod() 
bin()           eval()        int()          open()        str() 
bool()          exec()        isinstance()   ord()         sum() 
bytearray()     filter()       issubclass()   pow()         super() 
bytes()         float()        iter()         print()       tuple() 
callable()      format()      len()          property()    type() 
chr()           frozenset()   list()         range()       vars() 
classmethod()   getattr()     locals()       repr()        zip() 
compile()       globals()     map()          reversed()    __import__() 
complex()       hasattr()     max()          round() 
delattr()       hash()        memoryview()   set()

本文将这68个内置函数综合整理为12大类,正在学习Python基础的读者一定不要错过,建议收藏学习!

  • 和数字相关

    • 1. 数据类型

    • 2. 进制转换

    • 3. 数学运算

  • 和数据结构相关

    • 1. 序列

    • 2. 数据集合

    • 3. 相关内置函数

  • 和作用域相关

  • 和迭代器生成器相关

  • 字符串类型代码的执行

  • 输入输出

  • 内存相关

  • 文件操作相关

  • 模块相关

  • 帮  助

  • 调用相关

  • 查看内置属性

和数字相关

1. 数据类型

  • bool : 布尔型(True,False)
  • int : 整型(整数)
  • float : 浮点型(小数)
  • complex : 复数

2. 进制转换

  • bin() 将给的参数转换成二进制
  • otc() 将给的参数转换成八进制
  • hex() 将给的参数转换成十六进制
print(bin(10))  # 二进制:0b1010
print(hex(10))  # 十六进制:0xa
print(oct(10))  # 八进制:0o12

3. 数学运算

  • abs() 返回绝对值
  • divmode() 返回商和余数
  • round() 四舍五入
  • pow(a, b) 求a的b次幂, 如果有三个参数. 则求完次幂后对第三个数取余
  • sum() 求和
  • min() 求最小值
  • max() 求最大值
print(abs(-2))  # 绝对值:2
print(divmod(20,3)) # 求商和余数:(6,2)
print(round(4.50))   # 五舍六入:4
print(round(4.51))   #5
print(pow(10,2,3))  # 如果给了第三个参数. 表示最后取余:1
print(sum([1,2,3,4,5,6,7,8,9,10]))  # 求和:55
print(min(5,3,9,12,7,2))  #求最小值:2
print(max(7,3,15,9,4,13))  #求最大值:15

和数据结构相关

1. 序列

(1)列表和元组

  • list() 将一个可迭代对象转换成列表
  • tuple() 将一个可迭代对象转换成元组
print(list((1,2,3,4,5,6)))  #[1, 2, 3, 4, 5, 6]
print(tuple([1,2,3,4,5,6]))  #(1, 2, 3, 4, 5, 6)

(2)相关内置函数

  • reversed() 将一个序列翻转, 返回翻转序列的迭代器
  • slice() 列表的切片
lst = "你好啊"
it = reversed(lst)   # 不会改变原列表. 返回一个迭代器, 设计上的一个规则
print(list(it))  #['啊', '好', '你']
lst = [1, 2, 3, 4, 5, 6, 7]
print(lst[1:3:1])  #[2,3]
s = slice(1, 3, 1)  #  切片用的
print(lst[s])  #[2,3]

(3)字符串

  • str() 将数据转化成字符串
print(str(123)+'456')  #123456
  • format()     与具体数据相关, 用于计算各种小数, 精算等.
s = "hello world!"
print(format(s, "^20"))  #剧中
print(format(s, "<20"))  #左对齐
print(format(s, ">20"))  #右对齐
#     hello world!    
# hello world!        
#         hello world!
print(format(3, 'b' ))    # 二进制:11
print(format(97, 'c' ))   # 转换成unicode字符:a
print(format(11, 'd' ))   # ⼗进制:11
print(format(11, 'o' ))   # 八进制:13 
print(format(11, 'x' ))   # 十六进制(⼩写字母):b
print(format(11, 'X' ))   # 十六进制(大写字母):B
print(format(11, 'n' ))   # 和d⼀样:11
print(format(11))         # 和d⼀样:11
print(format(123456789, 'e' ))      # 科学计数法. 默认保留6位小数:1.234568e+08
print(format(123456789, '0.2e' ))   # 科学计数法. 保留2位小数(小写):1.23e+08
print(format(123456789, '0.2E' ))   # 科学计数法. 保留2位小数(大写):1.23E+08
print(format(1.23456789, 'f' ))     # 小数点计数法. 保留6位小数:1.234568
print(format(1.23456789, '0.2f' ))  # 小数点计数法. 保留2位小数:1.23
print(format(1.23456789, '0.10f'))  # 小数点计数法. 保留10位小数:1.2345678900
print(format(1.23456789e+3, 'F'))   # 小数点计数法. 很大的时候输出INF:1234.567890
  • bytes() 把字符串转化成bytes类型
bs = bytes("今天吃饭了吗", encoding="utf-8")
print(bs)  #b'xe4xbbx8axe5xa4xa9xe5x90x83xe9xa5xadxe4xbax86xe5x90x97'
  • bytearray()    返回一个新字节数组. 这个数字的元素是可变的, 并且每个元素的值得范围是[0,256)
ret = bytearray("alex" ,encoding ='utf-8')
print(ret[0])  #97
print(ret)  #bytearray(b'alex')
ret[0] = 65  #把65的位置A赋值给ret[0]
print(str(ret))  #bytearray(b'Alex')
  • ord() 输入字符找带字符编码的位置
  • chr() 输入位置数字找出对应的字符
  • ascii() 是ascii码中的返回该值 不是就返回u
print(ord('a'))  # 字母a在编码表中的码位:97
print(ord('中'))  # '中'字在编码表中的位置:20013
print(chr(65))  # 已知码位,求字符是什么:A
print(chr(19999))  #丟

for i in range(65536):  #打印出0到65535的字符
    print(chr(i), end=" ")

print(ascii("@"))  #'@'
  • repr() 返回一个对象的string形式
s = "今天n吃了%s顿t饭" % 3
print(s)#今天# 吃了3顿    饭
print(repr(s))   # 原样输出,过滤掉转义字符 n t r 不管百分号%
#'今天n吃了3顿t饭'

2. 数据集合

  • 字典:dict 创建一个字典
  • 集合:set 创建一个集合

frozenset() 创建一个冻结的集合,冻结的集合不能进行添加和删除操作。

3. 相关内置函数

  • len() 返回一个对象中的元素的个数
  • sorted() 对可迭代对象进行排序操作 (lamda)

语法:sorted(Iterable, key=函数(排序规则), reverse=False)

  • Iterable: 可迭代对象
  • key: 排序规则(排序函数), 在sorted内部会将可迭代对象中的每一个元素传递给这个函数的参数. 根据函数运算的结果进行排序
  • reverse: 是否是倒叙. True: 倒叙, False: 正序
lst = [5,7,6,12,1,13,9,18,5]
lst.sort()  # sort是list里面的一个方法
print(lst)  #[1, 5, 5, 6, 7, 9, 12, 13, 18]

ll = sorted(lst) # 内置函数. 返回给你一个新列表  新列表是被排序的
print(ll)  #[1, 5, 5, 6, 7, 9, 12, 13, 18]

l2 = sorted(lst,reverse=True)  #倒序
print(l2)  #[18, 13, 12, 9, 7, 6, 5, 5, 1]
#根据字符串长度给列表排序
lst = ['one''two''three''four''five''six']
def f(s):
    return len(s)
l1 = sorted(lst, key=f, )
print(l1)  #['one', 'two', 'six', 'four', 'five', 'three']
  • enumerate() 获取集合的枚举对象
lst = ['one','two','three','four','five']
for index, el in enumerate(lst,1):    # 把索引和元素一起获取,索引默认从0开始. 可以更改
    print(index)
    print(el)
# 1
# one
# 2
# two
# 3
# three
# 4
# four
# 5
# five
  • all() 可迭代对象中全部是True, 结果才是True
  • any() 可迭代对象中有一个是True, 结果就是True
print(all([1,'hello',True,9]))  #True
print(any([0,0,0,False,1,'good']))  #True
  • zip() 函数用于将可迭代的对象作为参数, 将对象中对应的元素打包成一个元组, 然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致, 则返回列表长度与最短的对象相同
lst1 = [1, 2, 3, 4, 5, 6]
lst2 = ['醉乡民谣''驴得水''放牛班的春天''美丽人生''辩护人''被嫌弃的松子的一生']
lst3 = ['美国''中国''法国''意大利''韩国''日本']
print(zip(lst1, lst1, lst3))  #<zip object at 0x00000256CA6C7A88>
for el in zip(lst1, lst2, lst3):
    print(el)
# (1, '醉乡民谣', '美国')
# (2, '驴得水', '中国')
# (3, '放牛班的春天', '法国')
# (4, '美丽人生', '意大利')
# (5, '辩护人', '韩国')
# (6, '被嫌弃的松子的一生', '日本')
  • fiter() 过滤 (lamda)

语法:fiter(function. Iterable)

function: 用来筛选的函数. 在filter中会自动的把iterable中的元素传递给function. 然后根据function返回的True或者False来判断是否保留留此项数据 , Iterable: 可迭代对象

def func(i):    # 判断奇数
    return i % 2 == 1
    lst = [1,2,3,4,5,6,7,8,9]
l1 = filter(func, lst)  #l1是迭代器
print(l1)  #<filter object at 0x000001CE3CA98AC8>
print(list(l1))  #[1, 3, 5, 7, 9]
  • map() 会根据提供的函数对指定序列列做映射(lamda)

语法 : map(function, iterable)

可以对可迭代对象中的每一个元素进行映射. 分别去执行 function

def f(i):    
  return i
  lst = [1,2,3,4,5,6,7,]
it = map(f, lst) # 把可迭代对象中的每一个元素传递给前面的函数进行处理. 处理的结果会返回成迭代器print(list(it))  #[1, 2, 3, 4, 5, 6, 7]

和作用域相关

  • locals() 返回当前作用域中的名字
  • globals() 返回全局作用域中的名字
def func():
    a = 10
    print(locals())  # 当前作用域中的内容
    print(globals())  # 全局作用域中的内容
    print("今天内容很多")
func()
# {'a': 10}
# {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': 
# <_frozen_importlib_external.SourceFileLoader object at 0x0000026F8D566080>, 
# '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' 
# (built-in)>, '__file__': 'D:/pycharm/练习/week03/new14.py', '__cached__': None,
#  'func': <function func at 0x0000026F8D6B97B8>}
# 今天内容很多

和迭代器生成器相关

  • range() 生成数据
  • next() 迭代器向下执行一次, 内部实际使用了__ next__()方法返回迭代器的下一个项目
  • iter() 获取迭代器, 内部实际使用的是__ iter__()方法来获取迭代器
for i in range(15,-1,-5):
    print(i)
# 15
# 10
# 5
# 0
lst = [1,2,3,4,5]
it = iter(lst)  #  __iter__()获得迭代器
print(it.__next__())  #1
print(next(it)) #2  __next__()  
print(next(it))  #3
print(next(it))  #4

字符串类型代码的执行

  • eval() 执行字符串类型的代码. 并返回最终结果
  • exec() 执行字符串类型的代码
  • compile() 将字符串类型的代码编码. 代码对象能够通过exec语句来执行或者eval()进行求值
s1 = input("请输入a+b:")  #输入:8+9
print(eval(s1))  # 17 可以动态的执行代码. 代码必须有返回值
s2 = "for i in range(5): print(i)"
a = exec(s2) # exec 执行代码不返回任何内容

# 0
# 1
# 2
# 3
# 4
print(a)  #None

# 动态执行代码
exec("""
def func():
    print("
 我是周杰伦")
"
"" )
func()  #我是周杰伦

code1 = "for i in range(3): print(i)"
com = compile(code1, "", mode="exec")   # compile并不会执行你的代码.只是编译
exec(com)   # 执行编译的结果
# 0
# 1
# 2

code2 = "5+6+7"
com2 = compile(code2, "", mode="eval")
print(eval(com2))  # 18

code3 = "name = input('请输入你的名字:')"  #输入:hello
com3 = compile(code3, "", mode="single")
exec(com3)
print(name)  #hello

输入输出

  • print() : 打印输出
  • input() : 获取用户输出的内容
print("hello""world", sep="*", end="@"# sep:打印出的内容用什么连接,end:以什么为结尾
#hello*world@

内存相关

  • hash() : 获取到对象的哈希值(int, str, bool, tuple). hash算法:(1) 目的是唯一性 (2) dict 查找效率非常高, hash表.用空间换的时间 比较耗费内存

s = 'alex'
print(hash(s))  #-168324845050430382
lst = [1, 2, 3, 4, 5]
print(hash(lst))  #报错,列表是不可哈希的
  id() :  获取到对象的内存地址
s = 'alex'
print(id(s))  #2278345368944

文件操作相关

  • open() : 用于打开一个文件, 创建一个文件句柄
f = open('file',mode='r',encoding='utf-8')
f.read()
f.close()

模块相关

__ import__() : 用于动态加载类和函数

# 让用户输入一个要导入的模块
import os
name = input("请输入你要导入的模块:")
__import__(name)    # 可以动态导入模块

帮  助

  • help() : 函数用于查看函数或模块用途的详细说明
print(help(str))  #查看字符串的用途

调用相关

  • callable() : 用于检查一个对象是否是可调用的. 如果返回True, object有可能调用失败, 但如果返回False. 那调用绝对不会成功
a = 10
print(callable(a))  #False  变量a不能被调用
#
def f():
    print("hello")
    print(callable(f))   # True 函数是可以被调用的

查看内置属性

  • dir() : 查看对象的内置属性, 访问的是对象中的__dir__()方法
print(dir(tuple))  #查看元组的方法
– 完 –

转自:https://mp.weixin.qq.com/s/tnNpA3i_u-SQ2j8RAj1BEw

使用Anaconda来搭python开发环境记录

换新电脑,之前的python环境是2.7,现在python都3.8了,所以想要与时俱进一下,准备2.7与3.8同时上。只能用虚拟环境来做多版本python并存,尝试一下大名鼎鼎的anaconda。

以下是相关的操作记录及知识备忘

Anaconda(https://www.anaconda.com/)就是可以便捷获取包且对包能够进行管理,同时对环境可以统一管理的发行版本。Anaconda包含了conda、Python在内的超过180个科学包及其依赖项。

conda search --full-name <package_full_name>

Anaconda 解决了官方 Python 的两大痛点。

第一:提供了包管理功能,Windows 平台安装第三方包经常失败的场景得以解决,

第二:提供环境管理的功能,功能类似 Virtualenv,解决了多版本Python并存、切换的问题。

Anaconda 的镜像地址默认在国外,用 conda 安装包的时候会很慢,目前可用的国内镜像源地址有清华大学的。修改 ~/.condarc (Linux/Mac) 或 C:\Users\当前用户名.condarc (Windows) 配置:

channels:

  • https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
  • defaults
    show_channel_urls: true

如果使用conda安装包的时候还是很慢,那么可以考虑使用pip来安装,同样把 pip 的镜像源地址也改成国内的,豆瓣源速度比较快。修改 ~/.pip/pip.conf (Linux/Mac) 或 C:\Users\当前用户名\pip\pip.ini (Windows) 配置(目录文件自己建):

[global]

trusted-host = pypi.douban.com
index-url = http://pypi.douban.com/simple

pip 安装指定版本
pip install jinja2==2.7

#升级conda虚拟环境对应的python版本
conda update conda
conda update anaconda
conda update python

#验证conda已被安装
conda --version

#更新conda至最新版本
conda update conda

#查看conda帮助信息
conda --help

#卸载conda
控制面板删除程序

conda create -n py36 python=3.6 

#切换环境
activate <env_name>

#退出环境
deactivate

#显示已创建环境
conda env list
conda info --envs

#复制环境
conda create --name <new_env_name> --clone <copied_env_name>

#删除环境
conda remove --name <env_name> --all

#精确查找
conda search --full-name <package_full_name>

#模糊搜索
conda search <text>

#获取当前环境中已安装的包信息
conda list

#在指定环境中安装包
conda install --name <env_name> <package_name>

#在当前环境中安装包
conda install <package_name>

#使用pip安装包(pip只是包管理器,无法对环境进行管理。因此如果想在指定环境中使用pip进行安装包,则需要先切换到指定环境中,再使用pip命令安装包)
pip install <package_name>

#卸载指定环境中的包
conda remove --name <env_name> <package_name>

#卸载当前环境中的包
conda remove <package_name>

# 更新所有包
conda update --all
conda upgrade --all

#更新指定包
conda update <package_name>
conda upgrade <package_name>

#导出安装的包
conda env export > environment.yml