面向对象基础语法

                                               面向对象基础

 

面向过程编程

 在讲面向对象前,我们已经学过了用函数进行编程,进而实现某些功能,那这个实现功能的过程就是面向过程编程

面向过程:

面向过程的 核心就是 “过程 “二字,面向过程的特性总的来讲就是将要实现的需求分解成若干个小功能,进而一步一步的去实现整个需求

但是也就是这个特性,当你需要对 某个功能进行修改或者扩展的时候,就会牵一发而动全身,你不单单要修改这个功能所在的代码块,整体的的代码你也需要进行修改。

适用场景:

面向过程编程适用于扩展性较低的程序,比如某个shell脚本;但是对于大型的程序而言面向过程编程的缺点就显而易见

面向过程的缺点:可扩展性差

那么当我们的需求过大时,我们应该怎样取写呢?此时就是面向对象编程大显身手的时候了!

面向对象编程(OOP)

OOP编程是利用“类”和“对象”来创建各种模型进而来实现需求,

面向对象的优点:

  • 程序的维护和扩展变得更简单,并且可以大大提高程序开发效率
  • 基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

面向对象的缺点:

  • 编程复杂度高

适用场景:

  • 用户需求经常变化
  • 互联网应用
  • 游戏开发
  • 企业内部应用等等

面向对象的几个核心特性如下:

  • 对象

对象的魔法:

  • Polymorphism 多态
  • Encapsulation 封装
  • Inheritance 继承

在这里我们先将继承,后续再讲多态和封装

继承 :

继承指的是类与类之间的关系,继承的功能之一就是用来解决代码重用问题。

继承是一种创建新类的方式,

class A:
    def __ionit__(self):
        pass

class B(A):    # B 继承 A
    pass

类:

类表示一组(或一类)对象 ,而每个对象都属于特定的类。类的主要任务是定义其实例将包含的属性方法,即,类是特征与技能的结合体!

类的创建:

class Name_class(object):         # 定义 类 
    
    def __init__(self):          # 构造函数(初始化函数)
    
        pass     

新式类 & 旧式类

类有两种写法:旧式类和新式类。

在Pyhton3之前,默认创建的是旧式类,之后就没有旧式类了,因为没人用

__metaclass__ = type            # 旧式类写法,Python 2 必须包含此行代码。Pyhton3之后不用写

class P:                    
    
    def __init__(self):
        pass
    
class P(object):                #新式类写法
    
    def __init__(self):
        pass

新式类和旧式类的区别:

1.只有在python2中才分新式类和经典类,python3中统一都是新式类
2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
4.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

构造函数(初始化函数):__init__  

构造函数用于对初始化新建对象的状态,所以又称为 “初始化函数 ”。构造函数不同于普通函数在于,在对象创建之后自动调用它

1 class Foobar:
2     def __init__(self,value= 38):   # 构造函数
3         self.somevar = value
4 
5 f= Foobar()
6 print(f.somevar)
7 
8 res:
9  38

 上述代码块,实例 f为何没有传参数?因为构造函数中有默认参数 value=38,那如果你给实例中传进去参数呢?

1 f = Foobar('This  is a constructor argment')
2 print(f.somevar)
3 
4 res:
5 
6 This  is a constructor argment

如上所见,由于类的构造函数中有默认参数,当你再传进一个参数后这相当于再次赋值,So, value就被替换掉了

类的对象(object):

一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同

对象有属性和方法组成。属性是属于对象的变量,而方法是存储在属性中的函数。

相比于其他函数,(关联的)方法有一个不同之处,那就是它总是将其所属的对象作为第一个参数,而这个参数通常被命名为 ” self ”。

1 class A(object):
2     def __init__(self):         # self 为类的实例化
3         
4         pass

那类是怎么实例化的呢?我们来看下以下代码:

class People:
    def __init__(self,name,age,sex):  
        self.name=name
        self.age=age
        self.sex=sex

r1= People('风清扬',18,'man')   # r1就是类People实例化对象

实例化分解为以下过程:

1. 对类People创建一个空对象r1(现在r1就是一个空的名称空间,也就是一个空字典), 

class People:
    pass

r1 =People()
print(r1.__dict__)   # 访问 r1 的名称空间

>>>: {}   

2. 将对象 r1 和参数传进类People,再由构造函数__init__对 对象r1 进行初始化特征,将特征以字典的形式传进对象r1的名称空间内

class People:
    def __init__(self,name,age,sex):  # 1. __init__(r1,'风清扬',18,'man')
        self.name=name
        self.age=age
        self.sex=sex
        # 2.
        # r1.name = '风清扬'
        # r1.age = 18
        # r1.age = 'man'
r1= People('风清扬',18,'man')    # 相当于 People.__init__(r1,'风清扬',18,'man')

print(r1.__dict__)

>>>: {'name': '风清扬', 'age': 18, 'sex': 'man'}

那对于对象的属性是不是也能进行增删改查呢?答案是肯定的呀!

#print(r1.name)      # 风清扬
print(r1.age)       # 18
print(r1.sex)       # man

# 增
r1.country = 'china'
print(r1.__dict__)        # {'name': '风清扬', 'age': 18, 'sex': 'man', 'country': 'china'}

#del r1.country
print(r1.__dict__)         # {'name': '风清扬', 'age': 18, 'sex': 'man'}

# 改
r1.age =20
print(r1.__dict__)         # {'name': '风清扬', 'age': 20, 'sex': 'man'}

类的属性:

数据属性:类中定义的变量

函数属性:类中定义的函数

1 class People():
2     country = 'Chain'  #数据属性
3     def func(self):    # 函数属性
4         pass

查看类的名称空间:

print(People.__dict__)
>>{'__module__': '__main__', 'country': 'Chain', 'func': <function People.func at 0x000002A1404929D8>, '__dict__': <attribute '__dict__' of 'People' objects>,
'__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}

数据属性的增删改查:

# 查  以下两种写法都可
print(People.country)
print(People.__dict__['country'])

# 增
People.name = 'lala'
print(People.name)  # lala  将会以字典的形式增加到类的名称空间末尾

#del People.name

# 改
People.test='haha'
print(People.test)  # haha
绑定方法:

对于类的两大属性:

数据属性:类中定义的变量,供所有对象使用

class People:
    country ='china'
    def __init__(self,name,age,sex):  # 1. __init__(r1,'风清扬',18,'man')
        self.name=name
        self.age=age
        self.sex=sex

r1= People('风清扬',18,'man')    # 相当于 People.__init__(r1,'风清扬',18,'man')
r2 =People('萧炎',18,'man')
r3 =People('林采儿',18,'man')

# 三个对象都调用类的数据属性country
print(People.country,id(People.country))
print(r1.country,id(r1.country))
print(r2.country,id(r2.country))
print(r3.country,id(r3.country))

输出:
china 2582506240520
china 2582506240520
china 2582506240520
china 2582506240520

  由上述结果可见,类的数据属性类和对象均能调用。不管哪个对象调用类的数据属性,其内存地址均相同。由此可知类的数据属性是所有对象共有的

函数属性:类中定义的函数,供绑定对象使用,称为绑定到对象的方法。谁调用此方法就会把谁当做第一个参数传进方法内

# 类调用函数属性
print(People.learn())
输出
TypeError: learn() missing 1 required positional argument: 'self'

# 看下此时learn是函数还是属性
print(People.learn)
输出
<function People.learn at 0x0000014E0B4F2A60>
print(r1.learn())
print(r2.learn())
print(r3.learn())
输出:
风清扬 is learning
萧炎 is learning
林采儿 is learning

由上述结果可见:类的函数属性类和对象也都能调用

  •   但当类调用时,此时函数还是函数,所以必须按照函数调用传参的规定,有几个参数就传几个
  •   当对象调用时,此时函数绑定对象为方法,由于函数参数为self,所以会自动传值,即将对象本身作为参数传进函数里

 类型即类

python中一切皆为对象,且python3中类与类型是一个概念,类型就是类

 1 print(list)
 2 >>><class 'list'>   # 类型即类
 3 
 4 # 实例化类list
 5 l1=list()
 6 l2=list()
 7 l3=list()
 8 
 9 #   均有方法append 相同的功能  但内存地址不同
10 print(l1.append)  <built-in method append of list object at 0x000002BD3300BD88>
11 print(l2.append) <built-in method append of list object at 0x000002BD3300BDC8>
12 print(l3.append) <built-in method append of list object at 0x000002BD3300BE08>
13 
14 # 操作绑定方法 传给谁谁才能调用
15 l1.append(0)
16 print(l1)    # [0]
17 print(l2)    # []
18 print(l3)    # []

 


posted @ 2018-08-06 18:08  繁华无殇  阅读(283)  评论(0编辑  收藏  举报