-
除了从一个父类继承外,Python允许从多个父类继承,称为多重继承
多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用
查看全部 -
类具有继承关系,并且子类类型可以向上转型看做父类类型
查看全部 -
如果要把一个类的实例变成 str,就需要实现特殊方法__str__():
__str__()用于显示给用户,而__repr__()用于显示给开发人员。
__repr__ = __str__
查看全部 -
def count(): #定义函数count fs = [] # 定义fs序列 for i in range(1, 4): #遍历(1-3) def f(): #定义函数f return i*i #f=i*i fs.append(f) #将f插入到fs序列 return fs #返回fs f1, f2, f3 = count() #取出count序列中的三个值
?
这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。
习题:用函数表示变量,保证值是变化的。
查看全部 -
如果一个属性由双下划线开头(__),该属性就无法被外部访问。
如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性
以单下划线开头的属性"_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问。
查看全部 -
判断类型:isinstance()
查看全部 -
继承:
新类不必从头编写
新类从现有类继承,自动拥有现有类的所有功能
新类只需编写现有类缺少的新功能
好处:
复用现有代码
自动拥有现有类所有功能
只需编写缺少的新功能
父类&子类
eg. Person & Student
特点:
子类和父类是is关系
错误的继承
eg. Student类和Book类是has关系(has关系应该是组合)
python的继承:
总是从某个类继承
不要忘记调用super()._init_
查看全部 -
和属性类似,方法也分实例方法和类方法
在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身
通过标记一个@classmethod,方法就可绑定到Person类上,而非类的实例
class Person(object):
count = 0
@classmethod
...
查看全部 -
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象
查看全部 -
虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。
实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样
查看全部 -
在Python中,函数其实是一个对象:
>>> f = abs >>> f.__name__ 'abs' >>> f(-123) 123
由于 f 可以被调用,所以,f 被称为可调用对象。
所有的函数都是可调用对象。
一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。
我们把 Person 类变成一个可调用对象:
class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __call__(self, friend): print 'My name is %s...' % self.name print 'My friend is %s...' % friend
现在可以对 Person 实例直接调用:
>>> p = Person('Bob', 'male') >>> p('Tim') My name is Bob... My friend is Tim...
单看 p('Tim') 你无法确定 p 是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。
查看全部 -
由于Python是动态语言,任何实例在运行期都可以动态地添加属性。
如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。
顾名思义,__slots__是指一个类允许的属性列表:
class Student(object): __slots__ = ('name', 'gender', 'score') def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = score
现在,对实例进行操作:
>>> s = Student('Bob', 'male', 59) >>> s.name = 'Tim' # OK >>> s.score = 99 # OK >>> s.grade = 'A' Traceback (most recent call last): ... AttributeError: 'Student' object has no attribute 'grade'
__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。
查看全部 -
try 的作用是捕获错误,并在捕获到指定错误时执行 except 语句。
查看全部 -
考察 Student 类:
class Student(object): def __init__(self, name, score): self.name = name self.score = score
当我们想要修改一个 Student 的 scroe 属性时,可以这么写:
s = Student('Bob', 59) s.score = 60
但是也可以这么写:
s.score = 1000
显然,直接给属性赋值无法检查分数的有效性。
如果利用两个方法:
class Student(object): def __init__(self, name, score): self.name = name self.__score = score def get_score(self): return self.__score def set_score(self, score): if score < 0 or score > 100: raise ValueError('invalid score') self.__score = score
这样一来,s.set_score(1000) 就会报错。
这种使用 get/set 方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。
但是写 s.get_score() 和 s.set_score() 没有直接写 s.score 来得直接。
有没有两全其美的方法?----有。
因为Python支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把 get/set 方法“装饰”成属性调用:
class Student(object): def __init__(self, name, score): self.name = name self.__score = score @property def score(self): return self.__score @score.setter def score(self, score): if score < 0 or score > 100: raise ValueError('invalid score') self.__score = score
注意: 第一个score(self)是get方法,用@property装饰,第二个score(self, score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。
现在,就可以像使用属性一样设置score了:
>>> s = Student('Bob', 59) >>> s.score = 60 >>> print s.score 60 >>> s.score = 1000 Traceback (most recent call last): ... ValueError: invalid score
说明对 score 赋值实际调用的是 set方法。
用 @property 修饰 grade 的 get 方法即可实现只读属性。
查看全部 -
Rational类实现了有理数运算,但是,如果要把结果转为 int 或 float 怎么办?
考察整数和浮点数的转换:
>>> int(12.34) 12 >>> float(12) 12.0
如果要把 Rational 转为 int,应该使用:
r = Rational(12, 5) n = int(r)
要让int()函数正常工作,只需要实现特殊方法__int__():
class Rational(object): def __init__(self, p, q): self.p = p self.q = q def __int__(self): return self.p // self.q
同理,要让float()函数正常工作,只需要实现特殊方法__float__()。
查看全部
举报