6-面向对象

 

编程范式:面向过程,面向对象

面向过程 VS 面向对象

面向过程编程

核心是过程二字

过程指的是解决问题的步骤,程序从上到下一步一步执行,设计思路是:将大问题分解成一个一个小问题或子程序,再将子程序 分解成小问题,直到借到足够简单的问题的思想

应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。

面向对象编程

核心是对象二字OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,解决扩展性

应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方

两者的优缺点:

面向过程编程

优点:复杂度的问题流程化,进而简单化

缺点:难维护,改一个组件,牵一发而动全身

 

面向对象编程

优点:易维护,易扩展,开发效率高

缺点:复杂度高,只有经过实例化后的对象交互才知道结果

面向对象的特征:

类,对象,封装,继承,多态

类(class)

一类有相同属性的对象的模型,在类中定义对象的相同属性和方法

 

类有两种属性:数据属性和函数属性

 

1. 类的数据属性是所有对象共享的,在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常 

 

2. 类的函数属性是绑定给对象用的,类中定义的函数(没有被任何装饰器装饰的),主要是给对象使用的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法

 

#python为类内置的特殊属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)

类的特殊属性(了解即可)

 对象(Object

 类的实例化——对象

通过类可以进行对象的交互

封装

封装:顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容

 

所以,在使用面向对象的封装特性时,需要:

 

  • 将内容封装到某处
  • 从某处调用被封装的内容

1,先封装

class foo(object):
    def __init__(self,name,age):   #构造方法
        self.name=name #普通属性
        self.age=age

#根据类创建俩个实例
#自动执行__init__方法
obj1=foo('aaa',10)
obj2=foo('bbb',12)

self 是一个形式参数,当执行 obj1 = Foo(''aaa'‘,10 ) 时,self 等于 obj1

                                  当执行 obj2 = Foo(''bbb'’,12 ) 时,self 等于 obj2

所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。

2,再调用封装

调用被封装的内容时,有两种情况:

  • 通过对象直接调用
  • 通过self间接调用

1、通过对象直接调用被封装的内容(对象.属性名)

class foo(object):
    def __init__(self,name,age):   #构造方法
        self.name=name #普通属性
        self.age=age
obj1=foo('aaa',10)
obj2=foo('bbb',12)
#直接通过对象调用
print(obj1.name,obj1.age)
print(obj2.name,obj2.age)

2,通过self间接调用被封装的内容

class Foo:
  
    def __init__(self, name, age):
        self.name = name
        self.age = age
  
    def detail(self):
        print(self.name)  #被封装起来的内容
        print(self.age)
  
obj1 = Foo('wupeiqi', 18)
obj1.detail()  # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18
  
obj2 = Foo('alex', 73)
obj2.detail()  # Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78

对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

继承

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容

对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

 

 

class F1:
    def __init__(self,name):
        self.n=name
        print('F1')

class F2:
    def __init__(self,a):
        self.a=a
        print('F2')

class F3:
    def __init__(self,b):
        self.b=b
        print('F3')

f1=F1('aaa')   #f1.n='aaa'
f2=F2(f1)     #f2=F2(F1('aaa'))
f3=F3(f2)    #f3=F3(F2(F1('aaa')))
print(f3.b.a.n)
多继承

 

多态

接口重用

 

补:

hasattr() getattr() setattr() 函数使用方法详解

hasattr(object, 'name')

判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。 

class Eg(object):
    name='zyp'
    age=12
    def eg(self):
        print("runuing ……")
        return  hasattr(self,'name')

e=Eg()
D=e.eg()
print(D)
# runuing ……
# True
print(hasattr(e,'age'))   #True
print(hasattr(e,'ID'))   #False

getattr(object, name[,default])

获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号

class Eg(object):
    name='zyp'
    age=12
    def eg(self):
        print('name',getattr(self,'name'))
        return  hasattr(self,'name')

e=Eg()
e.eg()  #name zyp
print('eg:',getattr(e,'eg'))    #打印内存地址  eg: <bound method Eg.eg of <__main__.Eg object at 0x02151E70>>
print('name',getattr(Eg,'name')) #  name zyp
getattr(e,'eg')()   #   name zyp 执行eg方法
print(getattr(e,'aa',123))      # 若方法或属性不存在,打印默认值 123 

setattr(object, name, values)
给对象的属性赋值,若属性不存在,先创建再赋值。

def eat(self):
    print("将类外面的方法装配到类里面",self.name)

class Eg(object):
    name='zyp'
    age=12
    def eg(self):
        print('name',getattr(self,'name'))
        return  hasattr(self,'name')

e=Eg()
e.eg()
print(hasattr(e,'id'))   #False
setattr(e,'id',1234)  #添加没有的属性
print(hasattr(e,'id'))  #True
print(e.id)  #  1234 打印对象新添加的属性
setattr(e,'talk',eat)    #talk为类中创建的方法名,创建类中不存在的方法。这样创建的是静态方法
e.talk(e)   #调用的时候使用talk,而不是eat,需要手动将对象传入

上例中talk写成固定值,因此在调用的时候可以使用e.talk,如果这里talk为用户输入的动态值,则需要先通过getattr()获取信息,通过调用getattr获得的结果去调用对应的属性或方法,

delattr 删除方法

delattr(e,'talk')
e.talk(e)   #AttributeError: 'Eg' object has no attribute 'talk'  此时已经删除了talk方法

 

 

def eat(self):
print("将类外面的方法装配到类里面",self.name)

class Eg(object):
name='zyp'
age=12
def eg(self):
print('name',getattr(self,'name'))
return hasattr(self,'name')

e=Eg()
e.eg()
print(hasattr(e,'id')) #False
setattr(e,'id',1234) #添加没有的属性
print(hasattr(e,'id')) #True
print(e.id) # 1234 打印对象新添加的属性
setattr(e,'talk',eat) #talk为类中创建的方法名,创建类中不存在的方法。这样创建的是静态方法
e.talk(e) #调用的时候使用talk,而不是eat,需要手动将对象传入
posted @ 2018-01-26 17:43  Aline2  阅读(119)  评论(0编辑  收藏  举报