前言

python相对于其它语言来说入门简单。入门后无论是web开发,还是爬虫都可以应付得了。大部分的工作都是在现有的框架下,继承某类,按照要求重写某些方法,然后就可以完成工作了。python进阶的那些知识,各种数据类型的合理使用,闭包,各种各样的协议,抽象基类,协程,属性描述符,元编程等等,平时写代码很少很少很少很少用到。作为面试官之一,面试了应该有20来个人了吧,就连装饰器(闭包的应用方向之一)也只有少数几个用过,甚至有的工作了3,4年的都基本没有自己写过装饰器。不会用到的原因很简单,这些进阶知识,一般是在写框架,写库等等才会用到,而这样的机会是很少的。这样来说,貌似没有一个很好的理由去学习那些进阶的python知识。虽说很少有机会去写,但是会有很多机会去看。各种框架代码,库基本上都会用到那些进阶的知识,不懂基本上看别人的代码就会出现,每个字母我都认识,但我就是不知道他是用来干啥的,为什么要这样用。总得来说就是,学进阶的python知识是为了看懂别人的代码,在这个基础上学习大牛们的优秀的用法,识别各种乱七八糟的用法。

识别各种乱七八糟的用法

下面那段代码是前人写的,作用是给每个线程都生成一个对象,然后在线程中共享这个对象。localmap这字典生命周期是和进程一样,每个线程都调用,随着线程不断的开关,localmap越来越大,导致了内存泄露。于是,有了版本2。

from threading import local

def threadlocal(localmap={}):

thread_name = threading.currentThread().getName()

if thread_name not in localmap:

# 线程共享的变量,其它线程无法访问

localmap[thread_name] = local()

return localmap[thread_name]

这里是版本2。之前内存泄露是因为线程的生命结束后,没有将localmap中对应的变量删除,导致的。既然如此,就想办法删掉那些不需要的项就好了。问题虽然是解决了,但是糟糕的解决办法。这段代码犯了两个严重的错误。1. 对于全局收集类的,不应该干扰收集对象的生命周期,这里可以用弱引用的容器,引用计数没有增加,不会影响对象的生命周期。2. threading库中的local用错了,它本身就实现了线程共享,线程间互不干涉,只需定义一个全局local对象,在线程中使用就好了。如果不懂得弱引用容器的使用场景,是识别不出这乱七八糟的用法的。当然,对于问题2,这个是对local这个库的误解,一知半解的就用了,闹出的笑话。

from threading import local

def threadlocal(localmap={}):

thread_name = threading.currentThread().getName()

if thread_name not in localmap:

# 线程共享的变量,其它线程无法访问

localmap[thread_name] = local()

if not order_process():

# 获取当前进程的线程

current_threads = [obj.getName() for obj in threading.enumerate()]

for key in localmap.keys():

if key not in current_threads:

localmap.pop(key)

return localmap[thread_name]

看懂代码

继续上面的例子。知道local的用法后,就有点好奇,它是怎么实现的。去看实现的代码如下。这段代码涉及到的知识有,我就不解释那些东西该怎么用了,有兴趣的去翻流畅的python这本进阶书。

实例创建与销毁:__new__, __init__, __del__

属性管理:__getattribute__, __setattr__,__delattr__

杂:__slots__

锁:RLock

垃圾回收机制

缺乏上面的知识是看懂local的实现是怎样的,只会一脸懵逼。local这个类实现的大体思路是,在创建local对象时,同时在线程对象的属性字典__dict__里面保存了local对象的属性字典,然后每次访问加锁,将线程对象保存的local对象的__dict__属性,载入local中。这里的操作很值得玩味,也很好的解决了上面的错误示范中的内存泄露的问题。想要看懂的话,去了解一下垃圾回收机制,然后再慢慢把味一下。这里的神操作,我觉得还是用弱引用来弄比较好,之所以不用,可能是这个库写的时候,还没弱引用那个库或者是说弱引用性能相对来说没这神操作的性能好等等吧。话说,用来弱引用可以不用加锁,并发性能应该会更高。

class _localbase(object):

__slots__ = '_local__key', '_local__args', '_local__lock'

def __new__(cls, *args, **kw):

self = object.__new__(cls)

key = '_local__key', 'thread.local.' str(id(self))

object.__setattr__(self, '_local__key', key)

object.__setattr__(self, '_local__args', (args, kw))

object.__setattr__(self, '_local__lock', RLock())

if (args or kw) and (cls.__init__ is object.__init__):

raise TypeError('Initialization arguments are not supported')

# We need to create the thread dict in anticipation of

# __init__ being called, to make sure we don't call it

# again ourselves.

dict = object.__getattribute__(self, '__dict__')

current_thread().__dict__[key] = dict

return self

def _patch(self):

key = object.__getattribute__(self, '_local__key')

d = current_thread().__dict__.get(key)

if d is None:

d = {}

current_thread().__dict__[key] = d

object.__setattr__(self, '__dict__', d)

# we have a new instance dict, so call out __init__ if we have

# one

cls = type(self)

if cls.__init__ is not object.__init__:

args, kw = object.__getattribute__(self, '_local__args')

cls.__init__(self, *args, **kw)

else:

object.__setattr__(self, '__dict__', d)

class local(_localbase):

def __getattribute__(self, name):

lock = object.__getattribute__(self, '_local__lock')

lock.acquire()

try:

_patch(self)

return object.__getattribute__(self, name)

finally:

lock.release()

def __setattr__(self, name, value):

if name == '__dict__':

raise AttributeError(

'%r object attribute '__dict__' is read-only'

% self.__class__.__name__)

lock = object.__getattribute__(self, '_local__lock')

lock.acquire()

try:

_patch(self)

return object.__setattr__(self, name, value)

finally:

lock.release()

def __delattr__(self, name):

if name == '__dict__':

raise AttributeError(

'%r object attribute '__dict__' is read-only'

% self.__class__.__name__)

lock = object.__getattribute__(self, '_local__lock')

lock.acquire()

try:

_patch(self)

return object.__delattr__(self, name)

finally:

lock.release()

def __del__(self):

import threading

key = object.__getattribute__(self, '_local__key')

try:

# We use the non-locking API since we might already hold the lock

# (__del__ can be called at any point by the cyclic GC).

threads = threading._enumerate()

except:

# If enumerating the current threads fails, as it seems to do

# during shutdown, we'll skip cleanup under the assumption

# that there is nothing to clean up.

return

for thread in threads:

try:

__dict__ = thread.__dict__

except AttributeError:

# Thread is dying, rest in peace.

continue

if key in __dict__:

try:

del __dict__[key]

except KeyError:

pass # didn't have anything in this thread

结束语

在写代码的过程中,确实是很少用到python的进阶知识,但是看代码的过程中是会经常用到的。如果想要知其然,知其所以然还是要学习python的进阶知识的。最后,虽然超级大牛说只有1%的python程序员会用到python那些高深的知识,但梦想还是要有的,万一有机会成为那1%,但没有知识储备,机会就溜掉了。

python进阶学什么意思_为什么要学习python进阶的知识相关推荐

  1. python需要学多久才能找到工作-为什么Python适合初学者,一般要学习多久

    为什么Python适合初学者?一般Python要学习多久?很多人都觉得,Python是一门很好学的语言,非常适合入门.但更多人都是不清楚具体原因的.那么,我们不如一起来看看Python为何更适合初学者 ...

  2. python越学越糊涂_你越努力,编程水平越差!这样学 Python ,更容易成为高手!...

    原标题:你越努力,编程水平越差!这样学 Python ,更容易成为高手! 从事 Python 这些年中,我见过很多 Python 教程和书籍,他们大都这样讲 : 先介绍 Python 的基本语法规则. ...

  3. python如何学的扎实_如何系统的学习python?

    Google的人机大战,人们一夜之间都知道了AlphaGo,而由此也使得Python成为了人工智能开发中的热门语言,于是越来越多的人开始学习Python,甚至连幼儿园.小学都将Python纳入了学习课 ...

  4. python学什么东西_什么是Python?你应该学习和使用它的13个理由

    如果您希望转向网站开发或软件开发,成为程序员中的一员,那么学习HTML,CSS和JavaScript的基础三重奏就不会出错.但要真正在拥挤的应用领域中脱颖而出,您还是需要学习其他编程语言. (上图为G ...

  5. 零基础自学python看什么书-零基础想要学习Python编程 ,不知道看哪本书?

    前言 Python现在非常火,语法简单而且功能强大,很多同学都想学Python!所以小的给各位看官们准备了高价值Python学习视频教程及相关电子版书籍,欢迎前来领取! 想要学习Python编程不知道 ...

  6. 计算机编程导论python程序设计答案-学堂在线_计算机科学与Python编程导论_作业课后答案...

    学堂在线_计算机科学与Python编程导论_作业课后答案 答案: 更多相关问题 近代中国完全沦为半殖民地半封建社会的标志是:A.<马关条约>B.<辛丑条约>C.<凡尔赛和 ...

  7. python如何初始化对象数组_如何理解Python中的面向对象编程?

    (由Python大本营付费下载自视觉中国) 作者 | Radek Fabisiak 译者 | 弯月,责编 | 郭芮 出品 | CSDN(ID:CSDNnews) 现如今面向对象编程的使用非常广泛,本文 ...

  8. python要学多久可以找到工作-学习Python多久能找到工作?老男孩Python开发培训

    学习Python好不好找工作?Python是目前市场上非常流行的编程语言,而且Python也引起了学习热潮,是不少人都想要学习的编程语言.与此同时,也有不少人都在担心Python是否好找工作呢?能不能 ...

  9. python基本语句实验心得_总算领会python语言学习心得

    python虽然好学,但是也要是付出努力之后,学懂了才会觉得好学,如果你没有动力,没有付出时间和精力,那对于你来说就是多好学也是非常的困难的!如何找到学习python的动力呢?以下是小编为你整理的py ...

最新文章

  1. mos管开关电路_MOS管的知识,看这一篇就可以了
  2. 【错误记录】Flutter 报错 ( Android Studio 中 main.dart 左侧不显示设备栏 )
  3. php 表单错误弹窗,PHP表单错误
  4. vue项目 预览照片的插件 v-viewer
  5. 实战渗透之一个破站日一天
  6. Google Guava多集
  7. 【转】ASP.NET MVC 3 Service Location, Part 5: IDependencyResolver
  8. Android RecyclerView拖放
  9. 基于TensorRT量化部署RepVGG模型
  10. 【Get深一度】信号处理(三)——3db带宽
  11. F - Ingenuous Cubrency ( UVa 11137 ,立方数之和,递推关系,算法进阶手册)
  12. 反复横跳的瞄准线!从向量计算说起!基于射线检测的实现!Cocos Creator!
  13. 方舟原始恐惧mod生物代码_《暗黑地牢》《方块方舟》周末免费试玩,多款游戏历史新低特惠...
  14. MFC ListCtrl的cheek框的全选和反选
  15. 【调试】你是一名优秀的侦探吗?
  16. linux+zip+加密+无交互,Linux下zip加密压缩
  17. 35个Python实战项目,完整源代码!
  18. 全世界的AI明星公司都在这!CB人工智能100深度拆解
  19. SDUT数据结构实验之链表一:顺序建立链表
  20. 华为服务器怎么查看cpu型号,华为RH2288H V2处理器性能测试_华为 FusionServer RH2288 V2_服务器评测与技术-中关村在线...

热门文章

  1. nginx 从vagant挂载目录中加载nginx.conf配置进行开机启动
  2. Hadoop案例之单表关联输出祖孙关系
  3. Knuth-Morris-Pratt 算法(KMP)
  4. IDEA在创建项目Project<NO SDK>最详细解决方法
  5. 关于电商搜索中Elasticsearch的正确使用姿势--配置篇
  6. 孩子脾气暴躁不听话怎么办
  7. ArangoDB的索引学习
  8. 【STM32学习】个人感悟
  9. 【随记】Flink 时间窗口的起始时间
  10. 怎样在百度地图上标注上自己公司的名称使别人能在搜索百度地图的同时在地图上能看见本公司地址?