python学习面向对象_python学习之-- 面向对象

面向对象(简写:OOP)

面向对象编程定义:利用类和对象来创建各种模型,来实现对真实世界的描述。

优点:使程序更容易理解和维护以及扩展代码。

类定义:用来描述具有相同的属性和方法的对象的集合。(简单讲就是个模板)

实例化定义:创建一个类的实例,类的具体对象。

对象定义:通过类定义的数据结构的实例

举例:一个最简单最小结构的类写法如下:

class class_name(object):

print('bababa')

举例一个正常类的写法:

class 类名称(object):

def __init__(self,name..) #构造函数

self.arg1 = name # 普通属性(成员变量),注:self就是实例对象本身,保存在对象内存里

def fun1(self): # 普通方法(动态属性)

print('...')

类进行实例化的运行原理:

1:将类中的对象和方法存储于内存中,

2:类进行实例化时,先在内存申请一块空间用于存放实例对象

3:把实例对象的内存地址和赋值参数传递给类模板

4:模板对传入的值进行self变量赋值,然后将self变量发送到实例对象内存空间。

类的三大特性:封装,继承,多态

-- 封装:类内部的数据和方法,对数据的赋值和内部调用对类外部而言是透明的。简单说就是隐藏实现的细节,使代码模块化。

特性:防止数据被随意修改,可以通过此对象对外接口进行直接访问。

另(类封装了属性和方法,对象封装了普通属性的值)

-- 继承:一个父类派生出的子类,在父类里定义的属性和方法自动被子类继承,实现一个角色的共同点和不同点的同时存在。使代码重用

注意:承可以多级继承,不过越多代码会越复杂,建议继承2-3级即可,继承的2个类之间应该是属于的关系。

-- 被继承的类命名:父类,基类,超类

-- 继承的类命名:子类,派生类

--种类:单继承和多继承。

--继承的过程:从一般到特殊的过程。

这里“一般”指:父类这样的对一个角色具有共同点。

这里“特殊”指:子类这样的对每一个角色的不同点的单独定义

--实现方式有2类:实现继承 和 接口继承

实现继承:指父类具有的功能,子类继承后直接调用不需再修改。

接口继承:指仅使用父类的属性和方法的名称,具体实现需要在子类里单独实现。

举例:单继承基本继承写法

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 classPerson(object):2 def __init__(self,name,age=22):3 self.NAME =name4 self.AGE =age5 self.storage = 'Normal'

6 deftalk(self):7 print('custom ......')8 classblackPerson(Person):9 def __init__(self,name,age,job):10 Person.__init__(self,name,age) #继承父类的属性(经典写法)

11 self.JOB =job12 deftalk(self):13 Person.talk(self) #继承父类的方法,不过这样没有意义,

14 print('非洲语言')15 classwritePerson(Person):16 def __init__(self,name,mess):17 Person.__init__(self,name)18 self.MESS =mess19 deftalk(self):20 print('speak ENGLISH')

View Code

-- 多态:同样的方法名的同时又对父类的方法做了不同的实现,这就是同一事务表现的多种形态。特点接口重用。

(举例:父类定义人会说话,子类分黄种人说汉语,白种人说英语)这就是多态。实现是改写父类的talk方法

举例:python中多态的写法

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 classAnimal(object):2 def __init(self,name):3 self.name =name4 deftalk(self):5 raise NotImplementedError('Subclass must implement abstrace method') #提示一个需要子类重写的错误

6 classCat(Animal):7 def talk(self): #子类重写

8 return 'miao'

9 classdog(Animal):10 def talk(self): #子类重写

11 return 'wang'

12 d =dog()13 c =Cat()14 def animal_talk(arg): #这里使用单独一个函数实现多态功能

15 returnarg.talk()16 print(animal_talk(d))17 print(animal_talk(c))

View Code

类的属性分如下:

-- 公有属性(静态字段):所有属于这个类的对象都可以访问的属性,(在类里直接定义的属性,class下一行定义的)

修改方法:1:通过对象修改,只改变该对象的属性值,相当于在对象本地内存新创建一个属性值(默认是引用类里的全局变量)

2:通过“类.公有属性名”修改,将改变的是全局属性值。

(疑问解释:类中的构造函数不都可以访问么,说的是实例对象,一个实例对象赋给的参数值在其他对象是无法访问的。所以构造函数不属于公有属性。

比如:实例化了2个对象a,b,其中实例化a的参数值(a=fun(1,2,3)),对象b就无法访问a的参数值。)

--成员属性(普通字段):构造函数中的self变量。

--私有属性:在类中以“__字符串”,双下划线开始的变量名即为私有属性。正常情况下私有属性在类外部是无法访问的。

访问方法有2种:1:通过在类里定义普通方法来return返回私有属性。2:强制访问写法:实例名._类名__私有属性名。

举例:使用第一个方法对外提供私有属性访问接口

def get_hart():

return self.__heart  #这里就直接返回私有属性值

类的方法分如下:

-- 普通方法:类中定义的常用方法。def定义的

小知识(如何将普通方法变为私有方法,1:单独写一个函数,比如名为fun2,然后重写对象的方法名,如d1.fun = fun2,最后执行此对象的方法d1.fun(d1))

-- 析构方法:语法:def __del__(self),在引用的变量被清空的时候或者通过手工del删除引用的变量后就会自动调用此方法进行内存回收。

一般用于程序的收尾,比如服务器端要停止服务,这时就需要它来清空客户端的连接。(另说明,只要类被实例化了就算是使用中,将不会自动回收)

-- 类方法:只能访问类变量(公有属性),不能访问实例变量,一般用在实例化对象后,无法对本身限定好的数据进行修改。

举例说明:

class f1:

name = 'jack'  #类变量

@classmethod #类方法

def fun(self):

print('classmethod %s' % self.name) # 这里数据只用使用name的值,无法修改

-- 静态方法:类里定义的方法,当不需要通过self往里传值的时候,就可以将此方法定义为静态方法。

举例说明:

class f1:

@staticmethod  # 静态方法写法

def fun():     # 注意 静态方法是不需要self传值,这里不写self

print('staticmethod')

调用方法为: f1.fun()

-- 属性方法:把一个方法变成一个静态属性,属性就不需要加括号调用,一般用于最终展示给用户看得结果

举例说明:

class f1:

def __init__(self):

self.__food = None # 为属性方法设置的私有属性(用于传值的,如果不使用setter方法,就可以不写)

@property #属性方法 (静态属性)默认这里只能打印固定数据,无法赋值

def fun(self): # 方法名

print('property: %s' % self.name,self.__food)

@fun.setter # 实现对属性方法赋值功能(注意这里的fun要和上面的方法名一致)

def fun(self,food):

print('set to food:',food)

self.__food = food    # 实现对私有属性的赋值

@fun.deleter # 实现删除属性方法的赋值

def fun(self):

del self.__food # 删除私有变量

调用方法:d = f1() ; d.fun # 打印属性方法

赋值方法:d.fun = 'baozi' # 赋值

删除赋值:del d.fun #删除

-- 内置方法:类里以:__名称__  这样结构的方法称为类的内置方法。

1:__doc__:类的描述信息,就是打印类名下的注释信息

2:__module__:表示当前操作的对象在哪个模块

__class__:表示当前操作的对象的类名

3:__init__:构造函数,通过类创建对象时,自动触发执行。

4:__del__:析构函数,当对象在内存中被释放时,自动触发。

5:__call__:对象后面加括号,触发执行。

举例说明:

class cla1(object):

def __call__(self, *args, **kwargs):

print(args,kwargs)

ins = cla1()

ins('jace','vivi',name='jack',age=22)  # 这里执行对象直接返回

返回:('jace', 'vivi') {'name': 'jack', 'age': 22}

6:__dict__:查看类或对象中的所有成员

print(类名.__dict__):打印类里的所有属性,不包括实例属性。print(实例名.__dict__):打印实例里所有的属性,不包括类属性

7:__str__:如果一个类中定义了此方法,那么在打印实例对象时,默认输出该方法的返回值

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 classPerson(object):2 def __init__(self, name, gender):3 self.name =name4 self.gender =gender5 def __str__(self):6 return '(Person: %s, %s)' %(self.name, self.gender)7 现在,在交互式命令行下用 print试试:8

9 >>> p = Person('Bob', 'male')10 >>> printp11 (Person: Bob, male)

View Code

8:__repr__:在python3里发现直接运行实例和使用pring 输出的状态和__str__ 相同。没看出有什么区别。但是通过sqlalchemy的创建表结构里可以看出区别,

通过在表结构里定义__str__返回来的数据是内存对象,通过在表结构里定义__repr__返回来的是转换后的字符串。

9:__getitem__ / __setitem__ / __delitem__ :用于索引操作,分别表示获取,设置,删除数据。

举例说明:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 classcla1(object):2 def __init__(self):3 self.data ={}4 def __getitem__(self, key):5 print("__getitem__: %s" %key)6 returnself.data.get(key)7 def __setitem__(self, key, value):8 print('__setattr__:%s,%s' %(key,value))9 self.data[key] =value10 def __delitem__(self, key):11 print('__delitem__:%s' %(key))12 ins =cla1()13 ins['name'] = 'jack' #调用setitem赋值

14 print(ins['name']) #调用getitem打印

15 print(ins.data) #打印实例属性

View Code

10:__new__:先于构造函数执行,构造函数是通过New来自动执行的。所以new是用来创建实例的,默认不用写

用处:可以在类进行实例化之前,通过new进行定制

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 classfoo(object):2 def __init__(self,name):3 self.name =name4 print('foo --init--')5 def __new__(cls, *args, **kwargs):6 print('foo --new--')7 return object.__new__(cls) #继承父类的new方法,如果注销这个,将不会自动执行构造函数,

8 #以上这行解释,类foo也是一个对象,这里的cls就是foo对象本身,也就相当于self概念。

9 f = foo('jack')

View Code

11:__metaclass__ : 指定当前类的原类名称,可以修改原类对当前类进行重新设置。在上面的new执行之前,

执行顺序为:第一步执行metaclass的init方法,第二步执行metaclass的call方法,第三步执行foo函数的new方法,第四步执行foo的initd方法,

这就是实例化整个路线图。

看代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 classMytype(type):2 def __init__(self): #第一步

3 super(Mytype.self).__init__(what,bases,dict)4 def __call__(self,*args,**kwargs): #第二步

5 .....6 classfoo(object):7 __metaclass__ = 'Mytype'

8 def __init__(self,..): #第四步 实例化完成

9 .....10 def __new__(cls,*args,**kwargs):11 return object.__new__(cls) #第三步

View Code

看图:

1312e7f86ed0d32844b53d029d54c8e8.png

类的 分类:有2种,第一种是:新式类。第二种是:经典类

-- 他们的区别:1:新式类需要在类名后加(object),经典类不需要,直接定义类名。2:继承方式写法不同。

-- 继承方式:在Python3中全部(新式类/经典类)为广度优先,在Python2中经典为深度优先,新式类为广度优先。

-- 继承写法:新式类使用super,经典类直接使用父类名初始化。

举例说明:

class A(object):

def __init__(self):

self.n = 'A'

class B(A):

def __init__(self):

self.n = 'B'

class C(A):

def __init__(self):

self.n = 'C'

class D(B,C):

pass

mess = fun4() ; print(mess.n)

解释:在python3中,无论是新式类还是经典类,继承顺序都是广度优先,以上顺序为:B->C-A

在python2中,新式类继承顺序为广度优先,如上,经典类是深度优先为:B->A->C

举例单独说明类中的self。(self == 实例对象)

class dog(object):

def __init__(self,name):

self.NAME = name

def sayhi(self):

print('wang wang wang , dog name %s' % (self.NAME))

dg1 = dog('jinba')  # 相当于:dog(dg1,'jinba') 注意:self == dg1(实例对象)

dg1.sayhi()     #  就相当于:dg1.sayhi(dg1),因为self在类中默认是传入的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值