在Python中,一个.py文件就称之为一个模块(Module)。 java
使用模块有什么好处? python
最大的好处是大大提升了代码的可维护性。其次,编写代码没必要从零开始。当一个模块编写完毕,就能够被其余地方引用。咱们在编写程序的时候,也常常引用其余模块,包括Python内置的模块和来自第三方的模块。 ssh
模块别名: 函数
try: import cStringIO as StringIO except ImportError: # 导入失败会捕获到ImportError import StringIO
面向对象的访问限制: spa
在Class内部,能够有属性和方法,而外部代码能够经过直接调用实例变量的方法来操做数据,这样,就隐藏了内部的复杂逻辑。 设计
若是要让内部属性不被外部访问,能够把属性的名称前加上两个下划线__,在Python中,实例的变量名若是以__开头,就变成了一个私有变量(private),只有内部能够访问,外部不能访问
调试
class Student(object): def __init__(self, name): self.__name = name def getName(self): return '实例变量:'+self.__name stu1 = Student('syc') print stu1.getName() # 实例变量:syc print stu1.__name # AttributeError: type object 'Student' has no attribute '__name'
有些时候,你会看到以一个下划线开头的实例变量名,好比_name,这样的实例变量外部是能够访问的,可是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我能够被访问,可是,请把我视为私有变量,不要随意访问”。 code
继承: orm
在OOP程序设计中,当咱们定义一个class的时候,能够从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。 对象
class Animal(object): def run(self): print 'animail is running' def eat(self): print 'animail is eating' class Horse(Animal): def run(self): print 'horse is running' Animal.eat(self) # 子类中调用父类的方法 hs = Horse() hs.run() print type(hs) 结果: horse is running animail is eating <class '__main__.Horse'>
若是要得到一个对象的全部属性和方法,可使用dir()函数:
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'eat', 'run']
class Horse(object): name = 'horse' def run(self): print 'horse is running' Animal.eat(self) # 子类中调用父类的方法 hs = Horse() print hasattr(hs, 'name') # 判断hs对象是否含有name属性,一样也能够进行方法的判断 setattr(hs, 'age', '18') # 增长的是实例变量,不能为对象设置新的方法 print getattr(hs, 'age') # 获得hs的age值,同时能够获得方法的变量
使用__slots__
正常状况下,当咱们定义了一个class,建立了一个class的实例后,咱们能够给该实例绑定任何属性和方法,这就是动态语言的灵活性
class Student(object): name = 'syc' def drink(self): print 'student is drunking' stu = Student() stu.age = 18 #给实例增长属性 print stu.age Student.age =19 # 给类添加属性 print Student.age def eat(self): print 'student is eating' from types import MethodType stu.eat = MethodType(eat, stu, Student) # 给Student的实例stu添加方法 stu.eat() stu2 = Student() # print stu2.eat() # AttributeError: 'Student' object has no attribute 'eat' Student.eat = MethodType(eat, None, Student) # 给类Student添加方法 stu2.eat()
class Student(object): __slots__ = ('name', 'age', 'eat') name = 'syc' def drink(self): print 'student is drunking' stu = Student() stu.address = 'fuzhou' 结果:AttributeError: 'Student' object has no attribute 'address'
方法也是一样的;
使用__slots__要注意,__slots__定义的属性仅对当前类起做用,对继承的子类是不起做用的
class Student(object): __slots__ = ('name', 'age', 'eat') name = 'syc' def drink(self): print 'student is drunking' class SubStudent(Student): pass substu = SubStudent() substu.address = 'fuzhou' print substu.address # fuzhou
使用@property
@property普遍应用在类的定义中,可让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减小了出错的可能性。
class Student(object): @property def aname(self): # 第一处 return self.__name @aname.setter # 第二处 def name(self, name): # 第三处 # if name == 'syc': # raise TypeError('name不能为syc') self.__name = name stu = Student() stu.name = 'syc' # 第四处 print stu.name # 第五处
新增的属性为name,不是__name
多重继承:
Mixin:在设计类的继承关系时,一般,主线都是单一继承下来的,若是须要“混入”额外的功能,经过多重继承就能够实现,这种设计一般称之为Mixin;python中的多重继承相似于java中的类组合;
在多重继承中,最大的问题就是当继承的父类中有同名的方法,这时的优先级问题:
class Grandfa(object): def hair(self): print 'no hair' class Father(Grandfa): pass class Mom(object): def hair(self): print 'hair' class Tom(Father,Mom): pass tom = Tom() tom.hair() # no hair 深度优先
定制类:
经过特殊变量,能够为咱们定制类,如:__slots__,__len__,__str__等
__str__:
class Student(object): pass # def __str__(self): # return 'a student instance' stu = Student() print stu # <__main__.Student object at 0x02634B90> class Student(object): # pass def __str__(self): return 'a student instance' stu = Student() print stu # a student instance
__iter__:
判断对象是否能够进行迭代:
class Student(object): pass from collections import Iterable print isinstance(stu,Iterable) # False
若是须要使对象可以迭代,能够在类中定义__iter__方法:
class Student(object): def __iter__(self): return self def next(self): self.a, self.b = self.b, self.a + self.b if self.b >100: raise StopIteration() return self.b stu = Student() from collections import Iterable print isinstance(stu,Iterable) # True stu.a, stu.b = 1,2 print [x for x in stu] # [3, 5, 8, 13, 21, 34, 55, 89]
Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
__getitem__
虽然能做用于for循环
class Student(object): def __getitem__(self, n): for x in range(n): self.a, self.b = self.b, self.a + self.b return self.b stu = Student() from collections import Iterable print isinstance(stu,Iterable) # False stu.a, stu.b = 1,2 print stu[1] # [3, 5, 8, 13, 21, 34, 55, 89]
__getattr__
经过__getattr__动态的定义类的属性和方法;
class Student(object): def __init__(self, name): self.name = name def __getattr__(self, item): if item == 'score': # 自动添加属性 return 99 if item =='getSocre': # 自动添加方法 return lambda :self.score * self.score stu = Student('syc') print stu.socre # None ==>当类定义了__getattr__时,即便没有定义socre,也不会报错:AttributeError: 'Student' object has no attribute 'socre' print stu.score # 99 print stu.getSocre() # 9801
class Student(object): def __init__(self, path=''): self.__path = path def __getattr__(self, item): if item == "users": return lambda user: Student("%s/users/:%s" % (self.__path, user)) else: return Student("%s/%s" % (self.__path, item)) def __str__(self): return self.__path print Student().users('syc').repos # /users/:syc/repos
或者:
class Student(object): def __init__(self, path=''): self.__path = path def __getattr__(self, item): return Student("%s/%s" % (self.__path, item)) def __str__(self): return self.__path def __call__(self, name): return Student("%s/:%s" % (self.__path, name)) print Student().users('syc').repos # /users/:syc/repos
一个对象实例能够有本身的属性和方法,
当咱们调用实例方法时,咱们用instance.method()来调用。能不能直接在实例自己上调用呢?相似instance()?在Python中,答案是确定的。
任何类,只须要定义一个__call__()方法,就能够直接对实例进行调用。请看示例:
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name) s = Student('syc') s() # My name is syc.
那么,怎么判断一个变量是对象仍是函数呢?其实,更多的时候,咱们须要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象,好比函数和咱们上面定义的带有__call()__的类实例:
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name) s = Student('syc') print callable(s) # True print callable([1, 2, 3]) # False print callable('ABC') # False print callable(None) # False
使用元类:
建立类有两种方法:自定义:class XXX,type(ClassName, parentClass, dict{fun,property})
def fn(self, name): print 'Hello %s'% name Hello = type('Hello', (object,), dict(hello=fn)) Hello().hello('world') # Hello world
要建立一个class对象,type()函数依次传入3个参数: