面向对象是一种编程方式,此编程方式的实现是基于对类和对象的使用。
类是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)。
对象,根据模板创建的实例(即对象),实例用于调用被包装在类中的函数。类是对象的定义 ,而实例是“ 真正的实物”,它存放了类中所定义的对象的具体信息。
面向对象三大特性:封装、继承和多态。
类的定义:
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾:
class ClassName: '类的帮助信息' #类文档字符串 class_suite #类体 #类的帮助信息可以通过ClassName.__doc__查看。 #class_suite 由类成员,方法,数据属性组成。
实例
#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: '所有员工的基类' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary #empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。 #第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法 #self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
self代表类的实例,而非类
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt()
#以上实例执行结果为: #<__main__.Test instance at 0x10d066878> #__main__.Test #从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.__class__ 则指向类。
#self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的: class Test: def prt(runoob): print(runoob) print(runoob.__class__) t = Test() t.prt() #以上实例执行结果为: #<__main__.Test instance at 0x10d066878> #__main__.Test
''' 创建实例对象 实例化类其他编程语言中一般用关键字 new,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式。 以下使用类的名称 Employee 来实例化,并通过 __init__ 方法接收参数。''' #"创建 Employee 类的第一个对象" emp1 = Employee("Zara", 2000) #"创建 Employee 类的第二个对象" emp2 = Employee("Manni", 5000) ''' 访问属性 您可以使用点号 . 来访问对象的属性。使用如下类的名称访问类变量:''' emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount ''' 可以使用以下函数的方式来访问属性: getattr(obj, name[, default]) : 访问对象的属性。 hasattr(obj,name) : 检查是否存在一个属性。 setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。 delattr(obj, name) : 删除属性。'''
类的成员
1、字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同。普通字段属于对象,静态字段属于类。
#coding=utf-8 class Province: # 静态字段 country = '中国' def __init__(self, name): # 普通字段 self.name = name # 直接访问普通字段 obj = Province('河北省') print(obj.name) # 直接访问静态字段 print(Province.country) ''' 由上述代码可以看出【普通字段需要通过对象来访问】【静态字段通过类访问】,在使用上可以看出普通字段和静态字段的归属是不同的。其静态字段在内存中只保存一份,普通字段在每个对象中都要保存一份。 应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段。 '''
2、类的方法包括实例方法、类方法、静态方法。
class Foo(object): def test(self)://定义了实例方法 print("object") @classmethod def test2(clss)://定义了类方法 print("class") @staticmethod def test3()://定义了静态方法 print("static")
#coding=utf-8 class Apple: def fun1(self): return 'normal' @staticmethod def fun2(): return 'staticmethod' @classmethod def fun3(cls): return 'classmethod' print Apple.fun1 print Apple.fun2 print Apple.fun3 print "-"*80 apple = Apple() print apple.fun1 print apple.fun2 print apple.fun3 print "-"*80 apple1 = Apple() print apple1.fun1 print apple1.fun2 print apple1.fun3 ''' 输出结果: 1、<unbound method Apple.fun1> 2、<function fun2 at 0x00000000022FC4A8> 3、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>> 4、---------------------------------------------------------------------------- 5、<bound method Apple.fun1 of <__main__.Apple instance at 0x00000000022FAE08>> 6、<function fun2 at 0x00000000022FC4A8> 7、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>> 8、---------------------------------------------------------------------------- 9、 <bound method Apple.fun1 of <__main__.Apple instance at 0x00000000022FAE48>> 10、<function fun2 at 0x00000000022FC4A8> 11、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>> --------------------- ------------------------------------------------------ ''' ''' 解析: 1、普通方法传入的第一个参数必须是self(当然也可以不用self,官方要求尽量用self),self是指实例对象本身; 2、静态方法无需传参; 3、类方法传入的第一个参数必须是class,是指类本身。 对比结果1,5,9行: fun1通过class调用时,它是未绑定的方法,而实例化apple和apple1之后,它属于绑定的方法,且实例化后的apple和apple1内存地址不同,因为它们属于不同的实例对象。 对比结果2,6,10行: 静态方法fun2通过class调用或者通过实例化后的对象调用,是没有任何区别的,全部都是指向同一块内存地址。可以简单的理解成静态方法与类或者实例没有任何关系,一旦调用后,它的内存地址即确定。 对比结果3,7,11行: 类方法fun3通过class调用或者通过实例化后的对象调用,是没有任何区别的,全部都是指向同一块内存地址。为什么?因为实例化对象apple和apple1调用类方法fun3传入的第一个参数是类本身Apple,也就是说apple.fun3 = apple1.fun3 = Apple.fun3。 区别总结: 1、静态方法装饰器下定义的方法属于函数(function); 2、类方法装饰器下定义的方法属于方法(method); 3、静态方法无需传入任何参数; 4、类方法传入的第一个参数必须是class本身cls; 5、静态方法与类方法一旦被调用,内存地址即确定。通过类调用和通过实例化对象调用的结果完全一样。 6、三种方法从不同层次上来对方法进行了描述:实例方法针对的是实例,类方法针对的是类,他们都可以继承和重新定义,而静态方法则不能继承,可以认为是全局函数 '''
3、如果你已经了解Python类中的方法,那么属性就非常简单了,因为Python中的属性其实是普通方法的变种。
#coding=utf-8 # ############### 定义 ############### class Foo: def func(self): pass # 定义属性 @property def prop(self): pass # ############### 调用 ############### foo_obj = Foo() foo_obj.func() foo_obj.prop #调用属性 ''' 由属性的定义和调用要注意一下几点: 定义时,在普通方法的基础上添加 @property 装饰器; 定义时,属性仅有一个self参数 调用时,无需括号 方法:foo_obj.func() 属性:foo_obj.prop 注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象 属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能 '''