解析
- 使用双层循环列表推导式
- 使用
sum(iterable,start=0)
,注意sum
函数带有一个缺省参数,默认是0- 使用
numpy
中的flatten()
函数- 使用
itertools
中的chain
解析
- 直接使用
b'字符串'的形式
- 使用
字符串.encode()
方法bytes(str,encoding="utf-8")
any
- 原型
any(iterable,/)
,其中下划线的作用:声明这个函数前面的参数只能是位置参数- 作用 返回
True
如果bool(elem)
为True
,对于任意的iterable
里面的elem
来说- 如果是
iterable
是空的,则返回False
all(iterable,/)
- 返回
True
,如果iterable
里面的所有的elem
的bool(elem)
都返回True
的时候,结果就是True
- 类似
and
的作用注意:
如果iterable
是空,则all
的返回值也是True
什么是Python的自省机制
python
在运行的时候可以获取对象的类型和属性python
是一门强类型的动态语言,强类型是指python很少使用隐式类型转换,动态语言是指python
在运行的饿时候允许改变对象的类型
dir()
翻译一下:
dir([object])
-> 字符串列表- 在没有参数的情况下调用,返回当前作用域中的名称
- 如果有参数,这个参数必须是一个对象.返回的的是对象的属性,按照字母顺序排序
- 如果对象重写了
__dir__()
方法,则执行重写的,否在就调用默认的dir()
方法- 对于模块对象,返回模块的属性
- 对于类对象,返回类的属性,以及父类的属性
- 对于其他任何对象,返回对象属性,类属性和基类属性
__dict__
- 如果是实例对象调用,则返回的是实例对象中的属性(方法不返回),不会返回父类中的属性
- 如果是类对象调用,则返回的是类对象的属性和方法,同样不考虑继承关系
__name__
并非所有的对象都有名称,但那些有名称的对象都将名称存储在其__name__
属性中.注: 名称是从对象而不是引用该对象的变量中派生的.
模块拥有名称,Python解释器本身被认为是顶级模块或者主模块.当以交互的方式运行Python
的时候,局部__name__
变量被赋予值__main__
.同样滴,当从命令行执行Python模块,而不是将其导入另一个模块的时候,其__name__
属性被赋予值__main__
,而不是该模块的实际的名称.这样,模块可以查看自身的__name__
值来自行确定它们自己正被如何使用,是作为另一个程序的支持,还是作为从命令行执行的主应用程序.下面这种惯用的语句在Python
中是很常见的:
if __name__ == "main":
# do something test
else:
# do nothing
type
type()
函数有助于我们确定对象是何种类型,它的返回值是类型对象:
id(地址/标识)
blist
和clist
变量引用同一个列表对象.id()
函数给任何给定对象返回唯一的标识符.属性
对象拥有属性,并且dir()
函数会返回这些属性列表.但是有时候,我们只想测试1个或者多个属性是否存在.如果对象具有我们正在考虑的属性,那么通常希望只检索该属性.这个任务可以由hasattr()
和getattr()
函数来完成.
可调用
可以调用表示潜在的行为(函数和方法)的对象.可以用callable()
函数来测试对象的可调用性:
实例
在type()
函数提供对象的类型的时候,也可以使用isinstance()
函数测试对象,以确定它是否是某个特定类型或者定制类的实例:
子类
关于类的问题,有一个继承的概念,有继承就有父子问题,这是现实生活中很正常的,在变成语言中也是如此.
继承的关系中,有一个关键的概念就是属性,子类会继承父类的属性.那么如果去判断一个类是否是另外一个类的子类呢?
可以使用issubclass()
来判断,注意这里判断的时候,自身也是自身的子类.
下面通过一个例子来表述本文中用到的概念和知识:
有时候我们会遇到这样的需求,需要执行对象的某个方法,或者是对对象的某个字段赋值,而这个方法名和字段名在编码的时候并不能确定,需要通过参数传递字符串的形式输入.举个具体的例子: 当我们需要实现一个通用的DBM
框架时,可能需要对数据对象的字段赋值,但我们无法预知用到这个框架的数据对象都有些什么字段,换言之,我们在写框架的时候需要通过某种机制访问未知的属性.
这个机制被称为反射(就是由对象自己告诉我们他有哪些属性),或者是自省(对象自己可以知道自己有哪些属性),用于实现在运行的时候来获取对象的信息.
1) 访问对象的属性
dir(obj)
调用这个方法可以返回包含
obj
大多数属性名的列表(会有一些特殊的属性不包含在内).obj的默认值是当前的模块对象.
hasattr(obj,attr):
这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值.
getattr(obj,attr):
调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为
bar
,则返回obj.bar
.
setattr(obj,attr,val):
调用这个方法将给
obj
的名为attr
的值属性赋值为val
.例如如果attr
为bar
,则相当于是obj.bar=val
.
访问对象的元数据模块(module)
__doc__:
文档字符串.如果模块没有文档,这个值是None.__name__:
始终是定义时的模块名,即使你用了import as为它取了别名,或者是赋值给另一个变量名.__dict__:
包含了模块里可用的属性名-属性的字典;也就是可以使用模块名.属性名访问的对象.__file__:
包含了该模块的文件路径.需要注意的是内建的模块没有这个属性,访问它会抛出异常.
实例(instance)
实例是指类实例化之后的对象.
__dict__:
包含了可用的属性名-属性字典.__class__:
该实例的类对象内建函数和方法(built-in functions and methods)
根据定义,内建(build-in
)模块是指用C
写的模块,可以通过sys
模块的builtin_module_names
字段查看都有哪些模块是内建的.这些模块中的函数和方法可以使用的属性比较少,不过一般也不需要再代码中查看它们的信息.
__doc__:
函数或者方法的文档__name__:
函数或者方法定义时的名字__self__:
仅方法可用,如果是绑定的(bound),则指向调用该方法的类(如果是类方法)或实例(如果是实例方法),否则为None
__module__:
函数或者方法所在的模块名函数(function)
这里特指非内建函数.注意,在类中使用def
定义的是方法,方法与函数虽然有相似的行为,但是他们是不同的概念.
__doc__:
函数的文档,__name__:
函数定义时的函数名__module__:
包含定义该函数的模块名,同样注意,是模块名而不是模块对象.__dict__:
函数的可用属性首先记住关键记忆:
__somename__
双下划线开头,双下划线结束的成员函数.程序员不用调用,Python解释器在适当的时机或者是特定的情况下自己调用.
自己的理解:
魔法方法其实就是这样一种方法,是Python语法的一种体现,某种固定的语法在会调用特定的魔法方法.
1) __init__():
对象的创建的时候__init__()会被自动的调用,用来根据传入的参数来初始化这个实例属性.
它本身是一个初始化的函数,并不是构造函数.
2) __new__():
- 对象在创建的时候首先是调用
__new__()
方法来创建类并返回这个类的实例.__new__
至少要有一个参数cls
,代表当前类,此参数在实例化的时候由Python
解释器自动识别__new__
必须要有返回值,返回实例化出来的实例,这点在自己实现__new__
时要特别注意,可以return
父类(通过super(当前类名,cls))__new__
出来实例,或者是直接是object
的__new__
出来的实例.如果__new__创建的是当前类的实例,会自动调用__init__函数,通过return 语句里面调用的__new__函数的第一个参数是cls来保证是当前类的实例,如果是其他类的类名,那么实际创建返回的就是其他类的实例,其实就不会调用当前类__init__函数
,也不会嗲用其他类的_init__函数
可以看到第二个并没有调用__init__
方法,因为__new__
方法没有创建对象并且返回,所以__init__()
方法对象可以进行实例化.
3) __del__ 函数
将实例化的对象销毁,即为析构函数.
调用的时机: 当内存被回收的时候自动触发,这里内存被回收包括两种情况:
- 页面执行完毕回收所有的变量
- 所有的对象被
del
的时候
class Bird(object):
def __init__(self, name):
self.name = name
def fly(self):
print("{} 鸟在飞翔!".format(self.name))
def __del__(self):
print("{} 鸟已经阵亡,被析构了!".format(self.name))
dark = Bird("鸭子")
dark.fly()
结果:
所有的对象被del的时候:
__call__()方法
调用时机:
- 当把对象当做函数调用的时候自动触发
- 可以模拟函数化操作
- 有点类似于在类中重载了
()
运算符,使得实例对象可以像调用普通的函数那样,以对象名()
的形式使用.
举个例子:
如果要想一个类对象,可以被当成一个函数被调用就要给它定义__call__
方法,比如:
可以看到,通过在Student
类中实现了__call__
方法,使得Student
的实例对象变为了可调用对象.
Python中,凡是可以将()
直接应用到自身并执行,都称为可调用对象.可调用对象包括自定义的函数,Python
内置函数以及本节所讲的类实例对象.
对于可调用的对象,实际上名称()
,可以被理解成 名称.__call__()
的简写.依然以上面的为例子,最后一行代码其实等价于:
然后自定义函数的例子:
__str__
,__repr__
__str__
- 作用: 返回一个字符串对象,主要让人友好的辨认的字符串
- 调用时机: 1>
str(obj)
2> format() 3> print()
__repr__:
- 作用: 用来输出一个对象的官方字符串形式.返回值必须是字符串对象,通常是用来给解释器看的.
- 调动时机: 1>
repr()
内置函数调用
注意:
如果
__repr__
已经定义,而__str__
未定义,则对象调用__str__ = __repr__
.
下面如果__str__
未定义的时候,则__repr__
会被调用