创建类:
class Person(object): pass xiaoming = Person() xiaohong = Person() print xiaoming print xiaohong print xiaoming==xiaohong
创建实例属性:Python是动态语言,对每一个实例,都可以直接给他们的属性赋值,实例的属性可以像普通变量一样进行操作。
#xiaoming和xiaohong是同一个类的对象 xiaoming = Person() xiaoming.name = 'Xiao Ming' xiaoming.gender = 'Male' xiaoming.birth = '1990-1-1' xiaohong = Person() xiaohong.name = 'Xiao Hong' xiaohong.school = 'No. 1 High School' xiaohong.grade = 2 xiaohong.grade = xiaohong.grade + 1
初始化实例属性:__init__()方法,创建实例时,该方法自动调用
class Person(object): def __init__(self,name,gender,birth,**kw): self.name=name self.gender=gender self.birth=birth for k,v in kw.iteritems(): setattr(self,k,v) xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student') print xiaoming.name print xiaoming.job
访问限制:Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无法被外部访问。
以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。
以单下划线开头的属性"_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问。
类属性:实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个。
class Person(object): address = 'Earth' def __init__(self, name): self.name = name
当实例属性和类属性重名时,实例属性优先级高。要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。
class Person(object): address = 'Earth' def __init__(self, name): self.name = name p1 = Person('Bob') p2 = Person('Alice') print 'Person.address = ' + Person.address p1.address = 'China' print 'p1.address = ' + p1.address print 'Person.address = ' + Person.address print 'p2.address = ' + p2.address
结果:
Person.address = Earth p1.address = China Person.address = Earth p2.address = Earth
定义实例方法:
- 一个实例的私有属性就是以__开头的属性,无法被外部访问,可以在类的内部访问
- 实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的
class Person(object): def __init__(self, name): self.__name = name def get_name(self): return self.__name
- class 中定义的实例方法其实也是属性,它实际上是一个函数对象,可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法
import types def fn_get_grade(self): if self.score >= 80: return 'A' if self.score >= 60: return 'B' return 'C' class Person(object): def __init__(self, name, score): self.name = name self.score = score p1 = Person('Bob', 90) p1.get_grade = types.MethodType(fn_get_grade, p1, Person) print p1.get_grade() # => A p2 = Person('Alice', 65) print p2.get_grade() # ERROR: AttributeError: 'Person' object has no attribute 'get_grade' # 因为p2实例并没有绑定get_grade
- 函数调用不需要传入 self,但是方法调用需要传入 self。
定义类方法:通过标记一个 @classmethod,该方法将绑定到类上,而非类的实例。
- 类方法无法获得任何实例变量,只能获得类的引用。
class Person(object): count = 0 @classmethod def how_many(cls): return cls.count def __init__(self, name): self.name = name Person.count = Person.count + 1 print Person.how_many() p1 = Person('Bob') print Person.how_many()
继承:
class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender class Teacher(Person): def __init__(self, name, gender, course): super(Teacher,self).__init__(name,gender) self.course=course t = Teacher('Alice', 'Female', 'English') print t.name print t.course
isinstance():判断变量的类型
isinstance(t,Person) 判断t是不是Person类实例
多态:对于同一方法,根据调用者不同而产生不同结果
多重继承:继承多个父类
多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次
class D(B, C): def __init__(self, a): super(D, self).__init__(a) print 'init D...'
获取对象信息:
- type()函数获取类型
>>> type(123) <type 'int'>
- dir() 函数获取变量的所有属性
>>> dir(123) # 整数也有很多属性... ['__abs__', '__add__', '__and__', '__class__', '__cmp__', ...]
- getattr() 和 setattr():已知一个属性名称,要获取或者设置对象的属性
getattr(s, 'name') # 获取name属性
setattr(s, 'name', 'Adam') # 设置新的name属性
特殊方法:
__str__():print自动调用,用于显示给用户
__repr__():用于显示给开发人员
__cmp__():sorted()函数按照默认__cmp__()函数进行排序
class Student(object): def __init__(self, name, score): self.name = name self.score = score def __str__(self): return '(%s: %s)' % (self.name, self.score) __repr__ = __str__ def __cmp__(self, s): if self.score > s.score: return -1 elif self.score == s.score: if self.name < s.name: return -1 else: return 1 else: return 1 L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)] print sorted(L)
__len__():返回元素个数,len()函数调用
class Fib(object): L=[0,1] def __init__(self, num): for i in range(2,num): j=Fib.L[i-1]+Fib.L[i-2] Fib.L.append(j) def __len__(self): return len(Fib.L) def __str__(self): return str(Fib.L) f = Fib(10) print f print len(f)
def gcd(a, b): if b == 0: return a return gcd(b, a % b) class Rational(object): def __init__(self, p, q): self.p = p self.q = q def __add__(self, r): return Rational(self.p * r.q + self.q * r.p, self.q * r.q) def __sub__(self, r): return Rational(self.p * r.q - self.q * r.p, self.q * r.q) def __mul__(self, r): return Rational(self.p * r.p , self.q * r.q) def __div__(self, r): return Rational(self.p * r.q , self.q * r.p) def __str__(self): g = gcd(self.p, self.q) return '%s/%s' % (self.p/g,self.q/g) __repr__ = __str__ r1 = Rational(1, 2) r2 = Rational(1, 4) print r1 + r2 print r1 - r2 print r1 * r2 print r1 / r2
__int__():int()函数自动调用
__float__():float()函数自动调用
@property:
- 重新实现一个属性的setter和getter方法
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
- 将一个方法 转换为只读属性
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 @property def grade(self): if self.score>=80: return 'A' elif self.score<60: return 'C' else: return 'B' s = Student('Bob', 59) print s.grade s.score = 60 print s.grade s.score = 99 print s.grade
__slots__:一个类允许的属性列表,限制当前类能拥有的属性
class Person(object): __slots__ = ('name', 'gender') def __init__(self, name, gender): self.name = name self.gender = gender class Student(Person): __slots__ = ('score',) #在Person类的基础上增加score属性 def __init__(self,name,gender,score): super(Student,self).__init__(name,gender) self.score=score s = Student('Bob', 'male', 59) s.name = 'Tim' s.score = 99 print s.score
__call__:把一个实例变成可调用对象需要实现的方法
class Fib(object): def __call__(self, num): a, b, L = 0, 1, [] for n in range(num): L.append(a) a, b = b, a + b return L f = Fib() print f(10)