Loading

面向对象基础


编程思想

指的是用计算机来解决人类实际问题的思维方式。

面向过程编程思想

核心是”过程“二字,过程即流程,指的是做事的步骤。

优点:

  • 复杂的问题流程化,进而简单化

缺点:

  • 扩展性非常差

面向过程的编程思想应用场景解析:

1、不是所有程序都需要频繁更迭,比如脚本文件。

2、即便一个软件需要频繁更迭,也并不代表这个软件所有的组成部分都需要一起更迭。

函数式编程

函数式编程并非用函数编程那么简单,而是将计算机的运算视为数学意义上的运算,比起面向过程,函数式更加注重的是执行结果而非执行的过程。

Python并不是一门函数式编程语言,但是仍提供了很多函数式编程的特性,如lamda,map,reduce,filter。

面向对象编程(OOP)

在现实生活中,对象指的是某个具体的事物,然后根据多个对象的相同属性归纳出类。例如四条腿、长毛、喵喵叫的是猫类,两条腿、头会秃、会说脏话的是人类。具体到某一个个体就是对象,比如你家养的肥猫和你到现在也没找到的女朋友,这些就是属于类中的一个具体对象。

面向对象编程的核心是对象二字,对象是特征与技能的结合体。

基于面向对象编程的思想编写程序,就好比是在创造一个世界,你就是这个世界的上帝,是一种上帝式的思维方式。

  • 优点:可扩展性强。
  • 缺点:编程的复杂度要高于面向过程。

在计算机中,则是先定义出类,类相当于一个容器,这个容器可以用来存放属性(变量)与方法(函数)。面向对象编程就是通过类实例化出一个个具体的对象,把原本分散开的相关数据与功能整合到一个个的对象里,这么做既方便使用,也可以提高程序的解耦合程度,进而提升了程序的可扩展性。需要强调的是,软件质量属性包含很多方面,面向对象解决的仅仅只是扩展性问题。


类与对象

类即类别/种类,是面向对象分析和设计的基石,如果多个对象有相似的数据与功能,那么该多个对象就属于同一种类。有了类的好处是:我们可以把同一类对象相同的数据与功能存放到类里,而无需每个对象都重复存一份,这样每个对象里只需存自己独有的数据即可,极大地节省了空间。所以,如果说对象是用来存放数据与功能的容器,那么类则是用来存放多个对象相同的数据与功能的容器。

需要强调的是:在程序中,必须要事先定义类,然后再调用类产生对象(调用类拿到的返回值就是对象)。产生对象的类与对象之间存在关联,这种关联指的是:对象可以访问到类中共有的数据与功能,所以类中的内容仍然是属于对象的,类只不过是一种节省空间、减少代码冗余的机制,面向对象编程最终的核心仍然是去使用对象。


类的定义

面向对象的基本思路就是把程序中要用到的、相关联的数据与功能整合到对象里,然后再去使用。

在Python中定义类的语法:

class 类名:
    variable1 = 'a'
    variable2 = 'b'
    def method(self):
        pass

类的命名应该使用"驼峰体",类体最常见的是变量的定义和函数的定义,但其实类体可以包含任意Python代码,类体的代码在类定义阶段就会执行,因而会产生新的名称空间用来存放类中定义的名字,可以打印类名.__dict__来查看类这个容器内命名空间盛放的东西。

class People:
    a = 10
    b = [1,2,3]
    def m1(self):
        pass
    
print(People.__dict__)

结果为一个字典:

{'__module__': '__main__', 'a': 10, 'b': [1, 2, 3], 'm1': <function people.m1 at 0x0000000002769700>, '__dict__': <attribute '__dict__' of 'people' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}

那么我们通过字典的key取出里面的a属性,:

print(People.__dict__['a'])
10

但Python提供了专门的属性访问语法:

print(People.a)  # 等同于print(People.__dict__['a'])

除了查看属性,也能修改或删除属性:

People.a += 10
print(People.a)
20

del People.a

实例化

调用类的过程称为将类实例化,得到的返回值就是程序中的对象,或称为一个实例:

# 加括号调用
libai = People()
print(libai)
<__main__.People object at 0x0000000001E44BB0>

一个类可以实例化出多个对象:

dufu = People()
wangwei = People()
print(dufu)
print(wangwei)

<__main__.People object at 0x0000000001E24BB0>
<__main__.People object at 0x0000000001E24B50>

类实例化出对象后,对象有自己的名称空间:

print(dufu.__dict__)
{}

给对象赋值

类中定义的属性是共享给所有对象用的,指向相同的内存地址。

print(id(libai.a))
print(id(wangwei.a))

8791138305984
8791138305984

现在要给对象赋予专有的属性:

libai.a = 'hello'
print(libai.a)

hello

给对象赋值影响的是对象的名称空间,不会影响类的名称空间。


修改类的属性

类的属性修改只会影响类名称空间,不会影响对象的名称空间。

class Boy:
    head = 1


print(Boy.head)  # 1
Boy.head = 2
libai = Boy()
libai.head = 3
print(libai.head)  # 3

类的属性修改后,对象在取值时,取的即是修改后的值。


对象的取值顺序

对象的名称空间里只存放对象独有的属性,对象在访问属性时,会先从对象本身的名称空间中查找,找不到则去类的名称空间查找,类若没有则会报错。

print(libai.a)
10

print(dufu.a)  # 对象没有则向类找.
20

类中定义的方法

在类中定义的函数也就是方法,主要是绑定给对象使用的,虽然也可以通过类名来调用类之内的方法,但这样使用它仅为一个普通函数,同样遵循函数的语法,有多少个形参则要传入多少个实参,也能有默认形参。

通过类名调用方法时:

class people:
    def m1(x):
        print(x)
        
people.m1('哈哈哈')
哈哈哈

在类中定义方法时,第一个位置形参有特殊作用,通过对象调用时,该方法就是对象的绑定方法。在调用时,会将对象本身当做实参传给该形参。约定俗成该形参为self,实际上也可以用其他名称。

通过对象调用时:

class people:
    x = 10
    def m1(self):
        print(f'这是self {self}')

libai = people()
libai.m1()   # 相当于 libai.m1(libai)
print(f'这是libai{libai}')

这是self <__main__.people object at 0x0000000002564BB0>
这是libai<__main__.people object at 0x0000000002564BB0>

由于通过对象调用类中方法时,会将对象自身当作实参传过去,所以一定要有个形参接收才行,否则会报错。


__init__方法

如果要在实例化时给对象赋予一些初始值,就可以使用__init__方法。在类实例化得到对象时,会触发__init__的执行。

之前给对象赋值:

class Boy:
    head = 1


libai = Boy()
libai.age = 18
print(libai.age)  # 18

使用__init__方法,将要赋予的初始值当成参数传进方法中:

class Boy:
    def __init__(self, age, height):
        self.age = age   # 前面age是属性名,后面这个age是变量名,接收传给age的参数。
        self.height = height

libai = Boy(18,190)
print(libai.age)
print(libai.height)

18
190

约定俗成__init__方法通常写为第一个方法。


类即类型

在Python3中统一了类与类型的概念,类就是类型。变量有三个指标:id、类型、值。我们用type()函数查看类型时,实际查看的就是它是什么类。

Python2中:

>>> a = 10
>>> type(a)
<type 'int'>

Python3中:

>>> a = 10
>>> type(a)
<class 'int'>

list的append方法原理

# Python内置类可以通过这种方式直接实例化对象,我们自己定义的类则要通过类名加括号的方式构建。
l1 = [1,2,3]
# 通过对象调用绑定方法.
l1.append(4)
# 通过类来调用方法则为普通函数,有几个形参则要传几个实参。
list.append(l1,5)
print(l1)

[1, 2, 3, 4, 5]
posted @ 2020-12-29 14:51  吃了好多肉  阅读(72)  评论(0编辑  收藏  举报