Python高级编程(14):python对象的自省机制
自省是通过一定的机制查询到对象的内部结构 ,Python中提供了很多的方法来查询对象的内部结构,比如: hasattr:查询对象是否有一个特性的属性 ;getattr:获取对象的属性 ;setattr:设置对象的属性 ;delattr:从一个对象中删除属性,这些都是比较常规的方法,我们今天主要来讲一下__dict__和dir()这两个方法,我们先来看一段代码:
1234567891011121314151617181920# 自省是通过一定的机制查询到对象的内部结构class Person: name = "user"class Student(Person): def __init__(self, school_name): self.school_name = school_nameif __name__ == '__main__': user = Student("家里蹲大学") # 通过__dict__来查询属性 print(user.__dict__) print(u ...
Python高级编程(13):数据封装和私有属性
在java或者c++里面,我们都有private,protected等来修饰类,从而达到数据封装和私有属性的目的,但是在Python里面,这些都是没有的,那么它是如何达到相同目的的呢?我们继续看段代码:
123456789101112131415161718from .class_method import Dateclass User: def __init__(self, birthday): self.birthday = birthday def get_age(self): return 2018-self.birthday.yearuser = User(Date(1990, 9, 12))print(user.get_age()) # 通过调用这个get_age方法来获取对象的年龄print(user.birthday) # 通过调用这个birthday属性来获取对象的出生信息# 输出结果:281990/9/12
现在我们不希望直接获取到自己的出生信息,需要对其进行隐藏,我们可以使用__birthday(前面有2个下划线)就能实现 ...
Python高级编程(12):类方法、静态方法和实例(对象)方法
定义在类中的代码块叫方法,Python的方法分为『实例方法』、『类方法』、『静态方法』,按照从前到后的顺序它们和实例对象的依赖程度依次降低。
我们先来看一段代码:
12345678910111213141516171819202122class Date: # 构造函数 def __init__(self, year, month, day): self.year = year self.month = month self.day = day def tomorrow(self): self.day += 1 def __str__(self): return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day)if __name__ == '__main__': new_day = ...
Python高级编程(11):类和实例属性的查找顺序—mro查找
我们先来看一段代码:
12345678910111213class A: name = "envse" def __init__(self): self.name = "job"a = A()print(a.name)# 输出结果:job
上面的运行结果是没有任何疑问的,那么我们为啥要专门说明一下这个类和实例的查找顺序呢?那是因为在多继承的条件之下,我们的继承关系就比较复杂了,一眼直接看出来就比较难了。
MRO算法MRO就是method resolution order,主要用于在多继承时判断所调用属性的路径(来自于哪个类)
经典类在Python2.2之前,我们Python里面的类称为经典类,经典类是一种没有继承的类,实例类型都是type类型,如果经典类被作为父类,子类调用父类的构造函数时会出错。这时MRO的方法为DFS(深度优先搜索(子节点顺序:从左到右))
在上面的图里面就是:A–>B–>D–>C–>E。也就是说会先往一条路深了查找,如果找不到就走另一条路。按照这种情况其实是非常合理的,B里 ...
Python高级编程(10):类变量和实例(对象)变量
关于类变量和实例变量,我相信很多小白刚开始学习Python的时候,一直没有搞懂里面初始化代码的意思,也没有哪本书介绍过这里面各个参数的意思,这里看完你就会有一个清醒的认识了。
我们先来看一段代码:
12345678910111213class A: aa =1 # 类变量 def __init__(self, x, y): # 这里的self是指这个类的一个实例化对象,不是类本身 self.x = x # 类实例化后的对象的x等于我们传进来的x (self.x属于我们实例化后的对象,不再属于类本身) self.y = y # 类实例化后的对象的y等于我们传进来的y (self.y属于我们实例化后的对象,不再属于类本身)a = A(2, 4)print(a.x, a.y, a.aa)# 输出结果:2 4 1
这里的a.x 其实就是self.x,a.y其实就是self.y,而这里的a.aa则是类的aa,为什么会这样呢,那是因为这关系到python变量的查找顺序,后面会说。它会首先查找这个实例化对象是否存在aa这个属性,如果不存在就往 ...
Python高级编程(9):isinstance和type的区别
老规矩,还是先看一段代码:
12345678910111213141516class A: passclass B(A): passb = B()print(isinstance(b, B))print(isinstance(b, A)) # 运行结果:TrueTrue
很容易理解因为isinstance判断的是继承关系,我们再来看一下type,不过我需要说明一下这个is 和==的区别:is用来判断这两个对象是不是同一个对象,就是判断id是否相同;而== 是用来判断这两个对象的value是不是相等。我们看一段代码,加深一下印象:
1234567891011121314151617class A: passclass B(A): passb = B()print(id(b), id(B), id(A))print(b is B) # 判断这两个对象是不是同一个对象,就是判断id是否相同print(b is A)# 输出结果:10722864 16500152 16499680FalseFalse
因此:is同一性运算符:比较判断两个对象是否相同,id做为判断 ...
Python高级编程(8):抽象基类(Abstract Base Classes模块)
在java里面,继承都是单继承的,只有接口才支持多继承,而且接口是不支持实例化的,同样在Python里面的抽象基类也是不支持实例化的,这一点要非常明确。
其次,在动态语言(Python,JavaScript等)里面,是没有变量的类型的,它只是一个符号,可以指向任何类型的变量,所以它就不支持多态了,从语言上来说就是多态语言了。动态语言在声明变量的时候,是不用声明变量的类型的,但是也就少了编译时检查错误的环节,这样我们写的代码出了错如果不运行,我们是很难知道的。这也就是动态语言与静态语言相比的一个劣势,无法做错误检查(没有编译,无法检查)。
在Python设计的理念里,鸭子类型是很重要的,我们要把它放在第一位。在java里面,某个类具有某个功能是看它继承了某个函数,但是在Python里面则是具有了某些魔法函数,就具有了某个功能。(鸭子类型和魔法函数构成了我们Python里面的协议)
回过来,我们谈抽象基类,抽象基类的意思是在这个基类里面,我们设定一些方法,然后所有继承这个基类的类都必须覆盖这个基类的方法;抽象基类是无法进行实例化的。可能还是不是很明白,我们通过两种情况来加深对它的理解。
第 ...
Python高级编程(7):鸭子类型和多态
这个概念的名字来源于James Whitcomb Riley提出的鸭子测试:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
我们先来看一段代码:
12345678910111213141516171819202122232425class Dog(object): def say(self): print("I am a dog")class Cat(object): def say(self): print("I am a cat")class Duck(object): def say(self): print("I am a duck")animal_list = [Dog, Cat, Duck]for animal in animal_list: animal().say()# 输出结果:I am a dogI am a catI am a duck
在上面的例子里面,3个类彼此之间没有任何的继承关系(除obj ...
Python高级编程(6):python魔法函数一览
前面说了那么多python的魔法函数,那么具体的魔法函数都有哪些呢?我在这里详细的列举出来。总的来说分为两大类,数学运算和非数学运算,下面就分别列举:
数学运算一元运算符:neg__(-)、__pos__(+)、__abs二元运算符:lt(<)、 __le__ <= 、 __eq__ == 、 __ne__ != 、 __gt__ > 、 ge >=
算术运算符:add + 、 sub - 、 mul * 、 truediv / 、 floordiv // 、 mod % 、 divmod divmod() 、 pow ** 或 pow() 、 round round()
反向算术运算符:radd 、 rsub 、 rmul 、 rtruediv 、 rfloordiv 、 rmod 、rdivmod 、 rpow
增量赋值算术运算符:iadd 、 isub 、 imul 、 itruediv 、 ifloordiv 、 imod 、ipow
位运算符:invert ~ 、 lshift << 、 __rshift__ >> 、 and ...
Python高级编程(5):python数据模型对python的影响
python数据模型其实就是python中内置的对象模型,那些内置的对象模型我们在之前进行过说明。python中内置的对象模型具有一些特殊方法,也就是我们前面说的魔法函数。
简单来说,Python数据模型就是Python内置的数据类型及其包含的特殊方法(魔法函数)。举个例子来说,我们在使用len()这个函数时,会调用__len__这个魔法函数;使用list[]时会调用__getitem__魔法函数;使用各类运算符也会调用其相对应的魔法函数。从根本上来说,list[ ]、+、-、*、/、for i in x这些写法只是为了更简洁和更具有可读性,但内部跟其他操作是一样的,也是通过特定方法(算法)来实现的,这就是魔法函数。
我们来看下面的一段代码:
1234567891011121314class Company(object): def __init__(self, employee_list): self.employee = employee_list def __getitem__(self, item): return self.employ ...