1、前言
前面一直是语法与面向过程编程,这张我们来学oop
2、直接开搞,python中如何创建一个类?
答: 用到关键字 class, 类名是MyFirst 括号的是 扩展的基类object
class MyFirst(object): 'my first class' #类也有文档字符串哦 foo = 100
3、静态变量(名字翻译好多:静态属性、类变量、静态数据)
class MyFirst(object): 'my first class' #类也有文档字符串哦 foo = 100 print(MyFirst.foo)
foo就是个静态变量………………
概念:它是属于类的,与类的实例对象无关,调用的时候用 类名.静态变量
4、方法
在类中的定义的函数,准确的说在python中叫方法(又称实例方法、对象方法)
class MyFirst(object): 'my first class' #类也有文档字符串哦 foo = 100 def myNoActionMethod(self): #self代表当前的类的实例对象,好吧,注意与普通函数的语法区别 pass
5、怎么调用方法呢?
first = MyFirst() #这里是得到MyFirst的一个实例对象 ,将引用赋值给变量first first.myNoActionMethod()
当然首先要得到实例对象,然后 通过 . 调用方法
class MyFirst(object): 'my first class' #类也有文档字符串哦 foo = 100 def myNoActionMethod(self): print("我是一个方法") first = MyFirst() first.myNoActionMethod()
输出结果:
>>> 我是一个方法
6、类特殊的静态变量
C.__name__ 类C的名字(字符串)
C.__doc__ 类C的文档字符串
C.__bases__ 类C的所有父类构成的元组
C.__dict__ 类C的属性
C.__module__ 类C定义所在的模块(1.5 版本新增)
C.__class__ 实例C对应的类(仅新式类中)
7、初始化一个类的实例对象
前面我们已经进行过初始化了,这里再总结下:
first = MyFirst() #在python中就是这么简单………… java中得用new哦
8、__init__(), 构造方法(还有其它名字:构造器,初始器,中文博大精深)
当类被调用时,咱们就去搞实例对象,python会检查是否实现了__init__()方法。
默认情况:如果没有定义或者叫做覆盖(重写)构造方法 __init__(),那就使用默认的,也就是说一个类肯定是有__init()__,没有重写,不代表没有,只是使用默认的。
重写情况:如果你重写了__init()__构造方法,那你创建一个实例对象的时候,就会调用你写的__init()__。
9、__new__(),又一个特殊的方法,先不说了,先知道有它就行
10、__del__(),该方法用于释放实例对象占用的内存,好吧,强行把实例对象占用的内存释放掉………………也是先知道即可…………
11、来个例子吧,包含__init__(), __new__()、__del__()………………叫停吧,书上的例子…慢慢深入
12、又谈到了如果计算一个类创建多少个实例对象,好家伙……用静态变量记录
上栗子:
class Person(object): count = 0 def __init__(self): #构造方法 Person.count = Person.count + 1 def __del__(self): #显示释放一个实例对象的方法 Person.count -= 1 def howManyObject(self): return Person.count one = Person() print(one.howManyObject())
例子重写两个特殊方法,用了一个类变量存储创建实例对象的数量
13、实例变量(又称:实例属性、对象变量)我的妈啊,被翻译就能折腾死是吧,呵呵
上例子:
class HotelRoom(object): 'Hotel room rate calculator' def __init__(self, rt, sales = 0.085, rm = 0.1): #构造方法,第一个self代表当前实例对象,这个不用传入,一个必选参数rt,两个默认值参数sales与rm '''HotelRoom default arguments: sales tax == 8.5% and room tax == 10%''' #首行的文档字符串 self.salesTax = sales #实例变量salesTax self.roomTax = rm #实例变量roomTax self.roomRate = rt #实例变量roomRate def calcTotal(self, days = 1): #一个实例方法,第一个参数self,代表当前实例对象,第二个是默认值参数days 'Calculate total: default to daily rate' daily = round((self.roomRate * (1 + self.roomTax + self.salesTax)), 2) #这里还调用了实例变量roomRate、roomTax、salesTax return float(days) * daily sfo = HotelRoom(29) #得到一个HotelRoom实例对象,将调用__init__()方法,因为构造方法有个必选参数,所以我们必须传入一个参数,这里传入参数为29 print(sfo.calcTotal(10)) #调用实例方法calcTotal,然后再调用print()函数
14、强调了__init__()不可返回其他对象
class Dog(object): def __init__(self): return 1 myDog = Dog()
输出结果:
Traceback (most recent call last): File "D:/temp/Dog.py", line 11, in <module> myDog = Dog() TypeError: __init__() should return None, not 'int' >>>
因为构造器只能返回实例对象,返回不是None的实例对象都会抛出异常TypeError,也就是说不要用return
15、又一次强调 dir()函数可以返回所有的类变量(返回的集合是List)、 __dirt__可以看到所有的实例变量(返回的集合是字典)
16、类变量(静态变量)再谈……
例子:
class Dog(object): eat = 'meat' def __init__(self): pass myDog = Dog() print(Dog.eat) #通过类名 print(myDog.eat) #通过实例对象的引用
类变量:可以通过类名访问、也可以用实例对象访问( 这里与java是一致哦)
不建议通过实例对象去访问类变量(java里也一样不建议这么做,你只需要知道即可)
17、self小结
self是什么?
答:任何一个实例方法定义中的第一个参数都是变量self,它表示调用此实例方法的实例对象
18、插一句啊,如果你的类没有继承任何类,那么默认继承的是object,所以你可以省略(ojbect),下面这俩是一样的…………
class Dog: eat = 'meat' def __init__(self): pass
class Dog(object): eat = 'meat' def __init__(self): pass
19、哈哈,终于到静态方法(又称类方法),等的哥哥花都快谢了…………
静态方法:类中的函数,属于类,不需要实例对象哦,就可以使用哦,亲爱的……
旧版本的python是这么创建静态方法的,看例子:
class TestStatic: def foo(): print("foo()") foo = staticmethod(foo) #利用staticmethod函数将foo函数变为静态方法,然后把函数引用赋值给foo
TestStatic.foo() # 利用类直接调用,算是正统 my = TestStatic() my.foo() #当然实例对象也可以调用静态方法,同样我们不推荐这样使用,你只需知道这种方式可以即可
另外一种方式,看例子:
class TestStatic2: def foo(cls): print("I am the best") foo = classmethod(foo) #利用classmethod函数将foo函数变为类方法,嘿嘿
20、python2.4以后静态方法的创建,我们当然直接用高大上的函数修饰符(又称作函数装饰器………………中文博大精深,翻译一会一个名字对于新人来说,越搞越混乱)
上栗子:
例子A
class TestStatic2: @staticmethod #高大上的函数修饰符,又叫装饰器 def foo(): print("I am the best")
例子B
class TestStatic2: @classmethod #用这个函数修饰符,也可,不过要注意有cls参数 def foo(cls): #<span style="color:#ff0000;">注意这里的cls参数</span> print("I am the best")
21、组合……代码复用的精髓,这个要慢慢体会的哦,亲
这里的类与类之间的关系,称为 has a…………
22、派生(又称继承),也是代码复用的精髓,也要慢慢体会哦,亲
这里的关系称作:is a………………
23、来吧,python怎么创建子类呀?怎么玩继承啊?
答:python支持多继承
class Man(Person, Thinking): #类Man, 继承自Person、Thinking pass
24、来个继承经典例子,这里不懂,就代表你还不明白面向对象
class Parent(object): #定义一个Parent类 扩展自object def printParent(self): print ('they are parents') class Child(Parent): #定义Child类扩展自Parent def printChild(self): print("hello child") par = Parent() #先来个Parent实例对象 par.printParent() #调用Parent的实例方法 chi = Child() #再来个Child实例对象 chi.printChild() #调用Child实例方法 chi2 = Child() #再整个Child实例对象 chi2.printParent() #调用Parent的实例方法
25、好吧,直接上重写吧(overriding)
class Father(object): def eat(self): print("老爹吃肉") class Son(Father): def eat(self): #俺们把从Father那里得到eat方法,又重写了,所以输出结果必然是……往下看 print("儿子吃素") s = Son() s.eat()
输出结果:
>>> 儿子吃素
疑问1:那我还想调用父类的eat方法呢?怎么办呢?
s = Son() s.eat() #这里调用的eat方法 Father.eat(s) #这里调用了父类的eat方法 不推荐这么用啊
疑问2:我想在子类重写的方法里直接调用父类的原方法呢?
建议用super
class Father(object): def eat(self): print("老爹吃肉") class Son(Father): def eat(self): super(Son, self).eat() #利用super函数可以办到 哈哈 print("儿子吃素")
也可以这样(不建议使用这个):
class Father(object): def eat(self): print("老爹吃肉") class Son(Father): def eat(self): Father.eat(self) print("儿子吃素")
26、继承体系下的__init__()方法,python中,不会硬性要求你必须调用父类的构造器,如果你没有调用,python可不会帮你调用哦。 这里和java可不一样
class Father(object): def walk(self): print("new Father().walk(self)") def __init__(self): print("老子构造方法") class Son(Father): def __init__(self): print("儿子构造方法") s = Son()
输出结果:
>>> 儿子构造方法
因为python坑爹的就是不会要求你调用父类的构造器,你如果想的话
显式的调用父类的构造器:
class Father(object): def walk(self): print("new Father().walk(self)") def __init__(self): print("老子构造方法") class Son(Father): def __init__(self): super(Son, self).__init__() #这里利用super函数,显示的调用父类的构造器,好吧,赞赞啊 print("儿子构造方法") s = Son()
27、python从2.2版本开始支持从 基本数据类型扩展子类、即 float int等等,先给老子知道这里就可以。
28、又谈到了多重继承,python啊python,你咋这牛逼呢?慢慢深入吧,一时半会不可能的………………
29、内建函数…………介绍…………一堆,慢慢深入
issubclass() 布尔函数判断一个类是另一个类的子类或子孙类。它有如下语法:
issubclass(sub, sup)
isinstance() 布尔函数在判定一个对象是否是另一个给定类的实例时,非常有用。它有如下
语法:
isinstance(obj1, obj2)
30、后面还有好多高级特性吧、什么 访问控制的 __ 、 _,哈哈,没事我会战胜苦难的,还有元类……还有…………总之类这里绝对没有那么简单,本章我们告一段落……………………………………………………………………加油…………………………深入…………………………
很喜欢这个函数……
def foo(data): if isinstance(data, int): print 'you entered an integer' elif isinstance(data, str): print 'you entered a string' else: raise TypeError, 'only integers or strings!' #raise用于抛出异常, 类似与java中的throw