Python学习笔记

这是我个人学python的一点笔记,方便自己以后查看知识点。
学习地址:廖雪峰Python教程


To-do List

  • 前面拉下的笔记
    • 暂时先挖坑,以后再来填

新东西往上记
今天看到python的一个知识点:协程。链接:看这里
协程看上去也是子程序(一个线程就是一个子程序),但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。
在一个子程序中中断,去执行其他子程序,不是函数调用,有点类似CPU的中断。比如子程序A、B:

def A():
    print('1')
    print('2')
    print('3')

def B():
    print('x')
    print('y')
    print('z')

假设由协程执行,在执行A的过程中,可以随时中断,去执行B,B也可能在执行过程中中断再去执行A,结果可能是:

1
2
x
y
3
z

在我不了解协程的概念时,我一定认为上述的代码结果是多线程的执行结果,但世界上这是协程的执行结果。
先说一下协程相比于多线程的优势:

  1. 执行效率高
    因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

  2. 不需要多线程的锁机制
    因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

以上是对协程概念的讲解。

实话讲导写这段话的时候,我依然对于协程没有一个完整的认识,只能是通过多线程去理解协程,但似乎二者在本质上就有所区分,实在是我的个人能力不够啊,记在这里的目的就是希望以后再次遇到这样的问题时,我已经可以理解协程的问题了。


偏函数

偏函数的意义:把一个函数的部分参数固定住(设置默认值),返回一个新的函数,使得调用新函数更加方便。
举例:
以int()为例子

>>> int('12345')
12345
>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565

可以看出int()函数的第二个参数可以将数值字符串转换为对应进制的数值。当我们需要对大量的数值字符串进行进制转化操作的时候,每次调用int()函数都需要填写进制,这个时候就可以使用偏函数了。

>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85

最后创建偏函数时,可以接受函数对象、*args**kw这3个参数,当传入:

int2 = functools.partial(int, base=2)

这种写法固定了int()函数的关键字参数base,也就是:

int2('10010')

相当于:

kw = {'base' : 2}
int('10010', kw)

注意,这是是int()

重新定义一个偏函数:

max2 = functools.partial(max, 10)

这时会把10作为*args的一部分自动加到左边,也就是:

max2(5, 6, 7)

等同于

args = (10, 5, 6, 7)
max(*args)

总结:当函数参数过多,需要简化时,使用functools.partial可以创建一个新的函数,简化调用。


模块

在Python中,一个.py文件就称之为一个模块(Module).
模块的的好处:

  1. 提高代码的可维护性。
  2. 提高代码的复用性,直接拉过来就可以用。
  3. 避免函数名和变量名冲突。冲突时前面加包名,当然不要和内置函数重名。

一个abc.py的python文件就是一个叫做abc的模块。
如果两个同名的python文件冲突了,再外面加个包名就可以了。
教程链接
实在懒得传图片了,直接看教程吧。
唯一需要注意的是:包下面必须要有一个__init__.py的文件,里面有没有内容都可以。如果没有这个文件python就会认为这是一个普通的文件夹。而且包里可以添加包,也就是嵌套。

使用包:

import sys

这里就是导入了一个python自带的包sys。
关于包的介绍与java大同小异,我个人对此算是比较了解了,如果有看到这里的读者,并且不太了解python的话,可以看这里

作用域
python中,通过_也就是下划线作为前缀来实现作用域的划分。

  1. 正常的函数和变量名是公开的,如:abdX123PI
  2. 类似__xxx__这样的变量是特殊变量,可以被直接引用,但是都有特殊用途,如__author____name__就是特殊变量,一般我们自己不要用这种变量名。
  3. 类似_xxx__xxx这样的变量是非公开的,不应该被直接引用的,如:_abc__abc等。

尽管private(私有)的函数和变量“不应该”直接被引用,而不是“不能”被直接引用,是因为python中没有任何方式可以限制访问private的函数或变量,但是,从编程习惯上不应该引用private函数或变量。

private函数的应用:

def _private_1(name):
    return 'Hello, %s' % name

def _private_2(name):
    return 'Hi, %s' % name

def greeting(name):
    if len(name) > 3:
        return _private_1(name)
    else:
        return _private_2(name)

外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public,意义在于封装和抽象。

第三方模块的安装
这里涉及到的一点就是python自带的pip命令,安装python时可以勾选这一项,如果没有勾选,就重新装一下记得勾选吧,哈哈哈哈。
以著名第三方库Pillow为例,说明下载方式。在命令行输入pip install Pillow,耐心等待下载万成交修可以啦。

>>> from PIL import Image
>>> im = Image.open('test.png')
>>> print(im.format, im.size, im.mode)
PNG (400, 300) RGB
>>> im.thumbnail((200, 100))
>>> im.save('thumb.jpg', 'JPEG')

模块使用方式。


OOP(面向对象编程)

前提是你有女朋友或者一对象。
有需要的看这里
封装继承多态

class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.score = score

    def print_score(self):
        print('%s: %s' % (self.name, self.score))
  1. 类中的构造方式用__init__来实现
  2. 类中的方法都一定有一个self参数代表类实例本身,其余一切都与普通函数相同。
  3. 和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:

    >>> bart = Student('Bart Simpson', 59)
    >>> lisa = Student('Lisa Simpson', 87)
    >>> bart.age = 8
    >>> bart.age
    8
    >>> lisa.age
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'age'

如果希望类的内部属性不被外部访问,可以在属性名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

class Student(object):

    def __init__(self, name, score):
        self.__name = name
        self.__score = score

    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))

执行结果
>>> bart = Student('Bart Simpson', 98)
>>> bart.__name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'

这里涉及到一个问题,如果外部不能访问,那我们如何对变量进行赋值和得到结果,可以使用set和get方法。这么做的一个意义在于可以对赋值来的参数做一个检查,判断参数是否合法。


获取对象的类型
这里主要提到的是使用type函数来判断对象的具体类型。

>>> type(123)
<class 'int'>
>>> type('str')
<class 'str'>
>>> type(None)
<type(None) 'NoneType'>

>>> type(abs)
<class 'builtin_function_or_method'>
>>> type(a)
<class '__main__.Animal'>

>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False

type用来判断基础类型如:intstr等。但是如何判断一个对象是否是函数呢?这里要注意的是types,后面多了一个s

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True

使用isinstance()
对于class的继承关系来说,使用type很不方便,我们需要判断class类型,可以用isinstance函数。
这里不贴代码了,isinstance判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。
另外,isinstance也可以判断基本类型。

>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
>>> isinstance(b'a', bytes)
True

还可以判断一个变量是否是某些类型中的一种

>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值