环境
虚拟机:VMware 10
Linux版本:CentOS-6.5-x86_64
客户端:Xshell4
FTP:Xftp4
python3.6
一、面向对象编程
1、概念
(1)面向对象编程(OOP),是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。面向对象是一种对现实世界理解和抽象的方法。
面向过程是一件事“该怎么做“,面向对象是一件事“该让谁来做”,然后那个“谁”就是对象,他要怎么做是他自己的事,反正最后一群对象合力能把事做好就行了。
面向对象三个特性:继承,封装,多态。
(2)类:具有相同属性和行为事物的统称:类(Class) 由3个部分构成:类的名称:类名;类的属性:一组数据;类的方法:允许对进行操作的方法 (行为)
(3)对象:某一个具体事物的存在 ,在现实世界中可以是看得见摸得着的,可以是直接使用的;
(4)类和对象关系:类就是创建对象的模板;
2、定义类
格式:class 类名: 方法列表
(1)定义类时有2种:新式类和经典类,下面的Car为经典类,如果是Car(object)则为新式类;
(2)类名的命名规则按照"大驼峰";
#定义一个Car类 class Car: def move(self): print('车正在移动...') def getCarInfo(self): print('车油耗数:%d, 颜色%s'%(self.oil, self.color))
3、创建对象
当创建一个对象时,就是用一个模子,来制造一个实物
格式:对象名 = 类名()
#创建对象 bmw=Car() #给对象bmw添加属性 bmw.color='白色' bmw.oil=30 #调用对象的方法 bmw.getCarInfo() bmw.move() print(bmw.color) print(bmw.oil)
(1)创建实例对象,一定在内存中有一块空间存放对象的数据信息。此时也可以通过实例对象bmw来访问属性或者方法,bmw是一个对象,它拥有属性(数据)和方法(函数);
(2)第一次使用bmw.color = '白色'表示给bmw这个对象添加属性,如果后面再次出现bmw.color = xxx表示对属性进行修改;
4、self
类定义的方法中的参数self,可以理解为自己,可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思。
(1)某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可;
(2)self可以不写self,方法中至少有一个参数,第一个参数表示当前对象。名字随便取,但是习惯都写self;
5、__init__()方法:初始化函数,用来完成一些默认的设定;该方法在创建对象后,就立刻被默认调用了。
(1)__init__()方法,在创建一个对象时默认被调用,不需要手动调用;
(2)__init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y);
(3)__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去;
示例:
class Car: def __init__(self): self.color='白色' self.wheel=4 self.oil=10 def move(self): print('车正在移动...') def getCarInfo(self): print('车油耗数:%d, 颜色%s'%(self.oil, self.color))
初始化函数使用入参:
class Car: def __init__(self,color,wheel,oil): self.color=color self.wheel=wheel self.oil=oil def move(self): print('车正在移动...') def getCarInfo(self): print('车油耗数:%d, 颜色%s'%(self.oil, self.color)) bmw=Car('黑色',4,10) print('汽车颜色=%s,轮子数量=%d,油耗数量=%d'%(bmw.color,bmw.wheel,bmw.oil))
6、__new__方法
(1)__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
(2)__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
(3)__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
(4)我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节
__new__与__init__关系:
(1)__new__方法(第一个执行)先于__init__方法执行;
(2)__new__方法是传入类(cls),而__init__方法传入类的实例化对象(self);
(3)__new__方法的第一个参数是这个类,而其余的参数会在调用成功后全部传递给__init__方法初始化;
(4)__new__和__init__想配合才是python中真正的类构造器;
示例:
class Dog(object): #创建对象 def __new__(cls,name,age): print('__new__方法') print("类内存地址:%s"%id(cls)) #return super().__new__(cls) ret=object.__new__(cls) print("实例化对象:%s"%ret) return ret def __init__(self,name,age): print('__init__方法') print("实例化对象:%s"%self) self.name=name self.age=age print('类内存地址:%s'%id(Dog)) d=Dog('haha',12) # 类内存地址:3992792 # __new__方法 # 类内存地址:3992792 # 实例化对象:<__main__.Dog object at 0x0000000002961390> # __init__方法 # 实例化对象:<__main__.Dog object at 0x0000000002961390>
7、__del__方法
当内存中销毁(释放)一个对象时回调__del__()方法;
import time class Animal(object): def __init__(self,name,age): print('__init__被调用...') self.__name=name self.__age=age def __del__(self): print('__del__被调用...') print('%s对象马上被干掉了'%self.__name) def __str__(self): return '名字'+self.__name+',年龄:'+str(self.__age) #创建对象 dog=Animal('哈皮狗',1) #删除对象 del dog # __init__被调用... # __del__被调用... # 哈皮狗对象马上被干掉了 cat=Animal('波斯猫',2) print(cat) cat2=cat cat3=cat print("---马上 删除cat对象") del cat print("---马上 删除cat2对象") del cat2 print("---马上 删除cat3对象") del cat3 print("程序2秒钟后结束") time.sleep(2) # __init__被调用... # 名字波斯猫,年龄:2 # ---马上 删除cat对象 # ---马上 删除cat2对象 # ---马上 删除cat3对象 # __del__被调用... # 波斯猫对象马上被干掉了 # 程序2秒钟后结束
关于对象被其他变量引用时,删除对象时的处理:
(1)当有1个变量保存了对象的引用时,此对象的引用计数就会加1
(2)当使用del删除变量指向的对象时,如果对象的引用计数不是1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除
8、魔法方法
在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
__str__()类似toString()
当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
9、id()用于打印对象内存地址
二、类和对象的属性
1、公有属性和私有属性
(1)Python中没有像C++中public和private这些关键字来区别公有属性和私有属性;
(2)它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。
2、类属性和实例属性
(1)类属性:所属类,类似C++,java中类的静态成员变量;
公有的类属性,在类外可以通过类和实例对象访问;
私有的类属性,类和实例对象均不能在类外访问。
(2)实例属性:在__init__通过self.XXX方式添加或者创建对象后,使用对象变量.XXX=数据时添加的
class People(object): name='Tom'#公有类属性 __age=10#私有的类属性 def __init__(self,address): self.address=address p=People('山东') #公有类属性与私有类属性 print(p.name) print(People.name) # print(p.__age)#报错:AttributeError: 'People' object has no attribute '__age' # print(People.__age)#报错:AttributeError: 'People' object has no attribute '__age' #实例属性与类属性 print(p.address) # print(People.address)#报错:AttributeError: type object 'People' has no attribute 'address' #通过实例(对象)去修改类属性 print(p.name)#Tom p.name='Jack' print(p.name)#实例属性会屏蔽掉同名的类属性 :Jack print(People.name)#Tom del p.name#删除实例属性 print(p.name)#Tom
注意:
如果需要在类外修改类属性,必须通过类去引用然后进行修改。
如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
三、类方法和静态方法
1、类方法
(1)是类所拥有的方法,用修饰器@classmethod来标识;
(2)第一个参数必须是类对象,一般以cls做标识(可用其他名称);
(3)可以通过实例对象和类调用类方法;
2、静态方法
通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数。
class Person(object): country='山东' @classmethod def getCountry(cls): return cls.country @classmethod def setCountry(cls,country): cls.country=country @staticmethod def getCountry2(): return Person.country pn=Person() #通过实例对象和类调用类方法 print(pn.getCountry())#山东 print(Person.getCountry()) #山东 pn.setCountry('北京') print(pn.getCountry())#北京 print(Person.getCountry()) #北京 #静态方法 print(Person.getCountry2())#北京
方法类别 |
语法 |
描述 |
类方法 |
@classmethod |
第一个形参cls,默认传递, 通过cls引用的必定是类对象的属性和方法 |
静态方法 |
@staticmethod |
没有默认传递的形参 |
对象方法(成员方法) |
def 方法名 |
第一个形参self ,默认传递,通过self引用的可能是类属性、也有可能是实例属性, 不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。 |
四、继承、多继承、多态
1、继承
(1)子类在继承的时候,在定义类时,小括号()中为父类的名字;
(2)父类的属性(不包括私有属性)、方法(不包括私有方法),会被继承给子类
class Animal(object): def __init__(self,name='动物',color='白色'): self.__name=name self.color=color def __test(self): print(self.__name) print(self.color) def test(self): print(self.__name) print(self.color) class Dog(Animal): def doTest(self): #print(self.__name)#不能访问到父类的私有属性 print(self.color) def doTest2(self): #self.__test()#不能访问父类中的私有方法 self.test() a=Animal() # print(a.__name)#报错:AttributeError: 'Animal' object has no attribute '__name' print(a.color) # a.__test()#报错:AttributeError: 'Animal' object has no attribute '__test' a.test() print('-'*30) d=Dog(name='小花',color='花色') d.doTest() d.doTest2()
2、多继承,即子类有多个父类,并且具有它们的特征
class Base(object): def test(self): print('---Base test---') class A(Base): def test(self): print('---A test---') class B(Base): def test(self): print('---B test---') class C(A,B): pass c=C() c.test()#---A test--- #可以查看C类的对象搜索方法时的先后顺序,C.__mro__算法得到一个元组 print(C.__mro__)#(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)
注意:按照继承顺序调用父类的方法
3、重写
所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
class Cat(object): def __init__(self,name): self.name=name self.color='黑色' def sayHello(self): print('-----Cat-----') class Bosi(Cat): def __init__(self,name): # 调用父类的__init__方法1(python2) Cat.__init__(self, name) # 调用父类的__init__方法2 super(Bosi,self).__init__(name) # 调用父类的__init__方法3 super().__init__(name) def sayHello(self): print('-----Bosi-----') bosi=Bosi('小花') bosi.sayHello()#-----Bosi----- print(bosi.name)#小花 print(bosi.color)#黑色
4、多态
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态
class Animal(object): def run(self): print('Animal is running...') class Dog(Animal): def run(self): print('Dog is running...') class Cat(Animal): def run(self): print('Cat is running...') def run_twice(animal): animal.run() run_twice(Animal())#Animal is running... run_twice(Dog())#Dog is running... run_twice(Cat())#Cat is running...
参考:
Python学习笔记