一切事物皆对象_基础篇

一 三大编程范式

编程范式即编程的方法论,标识一种编程风格


三大编程范式:

1.面向过程编程

2.函数式编程

3.面向对象编程

二 面向对象编程与面向对象设计

1.面向对象设计

面向对象设计(Object oriented design):将一类具体事物的数据和动作整合到一起,即面向对象设计

#相当于:类
def dog(name,gender,type):
    #狗的动作
    def jiao(dog):
        print('一条狗[%s],汪汪汪' % dog['name'])
    def chi_shi(dog):
        print('一条[%s] 正在吃肉' % dog['type'])
    #狗的属性
    def init(name,gender,type):
        dog1 = {
            'name':name,
            'gender':gender,
            'type':type,
            'jiao':jiao,    #动作
            'chi_shi':chi_shi,   #动作
        }
        return dog1
    return init(name,gender,type)

d1=dog('元吴','母','中华犬')
d2=dog('alex','母','藏敖')
print(d1)
print(d2)
d1['jiao'](d1)
d2['chi_shi'](d2)

什么是类?

类:把一类事物的相同的特征和动作整合到一起就是类,类是一个抽象的概念。

什么是对象?

对象:就是基于类而创建的一个具体的事物(指具体存在的),也是特征和动作整合到一起。

2.面向对象编程

面向对象编程(object-oriented programming):用定义类+实例/对象的方式去实现面向对象的设计

#用面向对象编程独有的语法class去实现面向对象设计
class Dog:
    def __init__(self,name,gender,type):   #实例化的过程,就是运行__init__
        self.name=name
        self.gender=gender
        self.type=type

    def bark(self):
        print('一条名字为[%s]的[%s],狂吠不止' %(self.name,self.type))

    def yao_ren(self):
        print('[%s]正在咬人' %(self.name))

    def chi_shi(self):
        print('[%s]正在吃屎' %(self.type))

dog1=Dog('alex','female','京巴')
dog2=Dog('wupeiqi','female','腊肠')
dog3=Dog('yuanhao','female','藏獒')

dog1.bark()
dog2.yao_ren()
dog3.chi_shi()

小结:

  在Python中,类和 OOP 都不是日常编程所必需的。尽管它从一开始设计就是面向对象的,并且结构上支持 OOP,但 Python 没有限定或要求你在你的应用中写 OOP 的代码。

用面向对象语言写程序和一个程序的设计是面向对象的,两者就是两码事

 三 类和对象

1.什么叫类:类是一种数据结构,就好比一个模型,该模型用来表述一类事物(事物即数据和动作的结合体),用它来生产真实的物体(实例)。

2.什么叫对象:睁开眼,你看到的一切的事物都是一个个的对象,你可以把对象理解为一个具体的事物(事物即数据和动作的结合体)

(铅笔是对象,人是对象,房子是对象,狗是对象,alex是对象,配齐是对象,元昊是对象)

3.类与对象的关系:对象都是由类产生的,上帝造人,上帝首先有一个造人的模板,这个模板即人的类,然后上帝根据类的定义来生产一个个的人

4.什么叫实例化:由类生产对象的过程叫实例化,类实例化的结果就是一个对象,或者叫做一个实例(实例=对象)

四 类的相关知识

1、初识类

在python中声明函数与声明类很相似。

声明函数

1
2
3
1 def functionName(args):
2      '函数文档字符串'
3       函数体

声明类

'''
class 类名:
    '类的文档字符串'
    类体
'''

#我们创建一个类
class Data:
    pass

#用类Data实例化出一个对象d1
d1=Data()

经典类与新式类

大前提:
1.只有在python2中才分新式类和经典类,python3中统一都是新式类
2.新式类和经典类声明的最大不同在于,所有新式类必须继承至少一个父类
3.所有类甭管是否显式声明父类,都有一个默认继承object父类(讲继承时会讲,先记住)
在python2中的区分
经典类:
class 类名:
    pass

经典类:
class 类名(父类):
    pass

在python3中,上述两种定义方式全都是新式类

 示例:

#经典类(python2.7)
class Chinese:
    '这是一个中国人的类'
    pass

print(Chinese)

#新式类(python3.0)

#实例化到底干了什么?
p1=Chinese() #实例化
print(p1)

2、属性

类是用来描述一类事物,类的对象指的是这一类事物中的一个个体

是事物就要有属性,属性分为

1:数据属性:就是变量

2:函数属性:就是函数,在面向对象里通常称为方法

注意:类和对象均用点来访问自己的属性

类的属性

理论:数据属性即变量,类的定义与函数又极其类似,其实可以用函数的作用域来理解类的属性调用。

类的数据属性

#定义一个中文人的类,然后在类中定义一个类的属性,政府是共产堂,这样,只要是中文人他们的党永远都是共产堂
#类属性又称为静态变量,或者是静态数据。这些数据是与它们所属的类对象绑定的,不依赖于任何类实例。
#如果你是一位Java或C++程序员,这种类型的数据相当于在一个变量声明前加上static关键字。

class Chinese:
    government='共产堂'

print(Chinese.government)

类的函数属性(又称为方法)

class Chinese:
    government='共产_党'
    def sui_di_tu_tan():
        print('90%的中国人都喜欢随地吐痰')

    def cha_dui(self):
        print('一个中国人-->%s<--插到了前面' %self)

Chinese.sui_di_tu_tan()

person1_obj='alex'
Chinese.cha_dui(person1_obj) #带参函数,所以调用时需要传入参数,将'alex'传给self

3、面向对象的三大属性

面向对象的三大特性是指:封装、继承和多态。

一、封装

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

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

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

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

                              当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2

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

第二步:从某处调用被封装的内容

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

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

1、通过对象直接调用被封装的内容

上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名

1
2
3
4
5
6
7
8
9
10
11
12
13
class Foo:
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
obj1 = Foo('wupeiqi'18)
print obj1.name    # 直接调用obj1对象的name属性
print obj1.age     # 直接调用obj1对象的age属性
 
obj2 = Foo('alex'73)
print obj2.name    # 直接调用obj2对象的name属性
print obj2.age     # 直接调用obj2对象的age属性

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

执行类中的方法时,需要通过self间接调用被封装的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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间接获取被封装的内容。

二、继承

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

例如:

  猫可以:喵喵叫、吃、喝、拉、撒

  狗可以:汪汪叫、吃、喝、拉、撒

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

注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。

那么问题又来了,多继承呢?

  • 是否可以继承多个类
  • 如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?

1、Python的类可以继承多个类,Java和C#中则只能继承一个类

2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先广度优先

  • 当类是经典类时,多继承情况下,会按照深度优先方式查找
  • 当类是新式类时,多继承情况下,会按照广度优先方式查找

经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

 

此外,新式类和经典类还有其他区别。看下面这段代码

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

class Teacher(person):
    def __init__(self,name,age,sex,salary,course):
        person.__init_(self,name,age,sex) #经典类
        super(Teacher,self).__init__(name,age,sex) #新式类

代码中Teacher类继承了person类,在构造函数中使用了两种继承的方式。

classical vs new style:

  • 经典类:深度优先
  • 新式类:广度优先
  • super()用法

三、多态 

 多态是为实现接口的重用性,多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。python是不支持多态的,其实python也无需支持多态。因为python的语言类型,python可以使用“鸭子类型”来实现多态。我的理解就是定义新的函数,通过函数改变调用的方式。

class F1:
    pass


class S1(F1):

    def show(self):
        print 'S1.show'


class S2(F1):

    def show(self):
        print 'S2.show'


# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象

def Func(F1 obj):
    """Func函数需要接收一个F1类型或者F1子类的类型"""
    
    print obj.show()
    
s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show

s2_obj = S2()
Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show

Python伪代码实现Java或C#的多态
class F1:
    pass


class S1(F1):

    def show(self):
        print 'S1.show'


class S2(F1):

    def show(self):
        print 'S2.show'

def Func(obj):
    print obj.show()

s1_obj = S1()
Func(s1_obj) 

s2_obj = S2()
Func(s2_obj) 

Python “鸭子类型”
Python “鸭子类型”

4、总结

以上就是本节对于面向对象初级知识的介绍,总结如下:

  • 面向对象是一种编程方式,此编程方式的实现是基于对  和 对象 的使用
  • 类 是一个模板,模板中包装了多个“函数”供使用
  • 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
  • 面向对象三大特性:封装、继承和多态

类和对象在内存中是如何保存?

类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份,大致如下图:

 

如上图所示,根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个类对象指针,该值指向当前对象的类。

当通过 obj1 执行 【方法一】 时,过程如下:

  1. 根据当前对象中的 类对象指针 找到类中的方法
  2. 将对象 obj1 当作参数传给 方法的第一个参数 self 
原文地址:https://www.cnblogs.com/lixiaoliuer/p/6476058.html