Introduction

三要素

  1. 类名 这类事物的名字,满足大驼峰命名法 大驼峰命名法

    1. 每个单词的首字母大写, 如: StudentAge
    2. 单词与单词之间没有下划线 大驼峰命名法和小驼峰命名法
  2. 属性 这类事物具有什么样的特征

  3. 方法 这类事物具有什么样的行为

三要素的确定

  1. 类名的确定 名词提炼法 分析整个业务流程,出现的名词,通常就是找到的类。
  2. 属性的确定 对对象的特征描述,通常可以定义成属性
  3. 方法的确定 对象具有的行为(动词),通常可以定义成方法

提示:需求中没有涉及的属性或者方法在设计类时,不需要考虑

面向对象三大特性

面向对象三大特性

  1. 封装:根据职责将属性和方法封装到一个抽象的类中

    • 定义类的准则
  2. 继承:实现代码的重用,相同的代码不需要重复的编写

    • 设计类的技巧
    • 子类针对自己特有的需求,编写特定的代码
  3. 多态:不同的子类对象调用相同的父类方法,产生不同的执行结果

    • 多态可以增加代码的灵活度
    • 继承重写父类方法为前提
    • 是调用方法的技巧,不会影响到类的内部设计

定义简单的类

方法的定义格式和之前学习过的函数几乎一样

区别在于第一个参数必须是 self,大家暂时先记住,稍后介绍 self

注意:类名的命名规则要符合大驼峰命名法

示例:

1
2
3
4
5
6
7
8
9
10
11
12
class Cat:
"""这是一个猫类"""

def eat(self):
print("小猫爱吃鱼")

def drink(self):
print("小猫在喝水")

tom = Cat()
tom.drink()
tom.eat()

引用概念的强调 :在面向对象开发中,引用的概念是同样适用的

  • 在 Python 中使用类创建对象之后,tom 变量中仍然记录的是对象在内存中的地址

  • 也就是 tom 变量引用了新建的猫对象

  • 使用 print 输出对象变量,默认情况下,是能够输出这个变量引用的对象是由哪一个类创建的对象,以及在内存中的地址(十六进制表示)

    1
    2
    3
    4
    5
    addr = id(object1)
    print("%x" % addr) # %x 16 进制

    或者直接
    print(object1)

给对象增加属性

在 Python 中,要给对象增加属性,非常的容易,但是不推荐使用

  • 因为:对象属性的封装应该封装在类的内部

只需要在类的外部的代码中直接通过,设置一个属性即可

  • 在日常开发中,不推荐在类的外部给对象增加属性

    • 如果在运行时,没有找到属性,程序会报错
  • 对象应该包含有哪些属性,应该封装在类的内部

1
2
3
4
class Cat:
...
tom = Cat()
tom.name='Tom'

self

self 是调用方法的对象的引用, 由哪一个对象调用的方法,方法内的 self 就是哪一个对象的引用

  • 在类封装的方法内部,self 就表示当前调用方法的对象自己

  • 调用方法时,程序员不需要传递 self 参数

  • 在方法内部(定义方法时, self 作为第一个参数,否则就不能通过 self. 访问对象的方法了)

    • 通过 self.访问对象的属性

    • 通过 self.调用对象其他的方法

内置方法和属性

dir 查看属性、方法

在 Python 中对象几乎是无所不在的,我们之前学习的变量、数据、函数都是对象在 Python 中可以使用以下两个方法验证

The dir() method tries to return a list of valid attributes of the object.

  1. 标识符/数据后输入一个,,然后按下 TAB 键,ipython 会提示该对象能够调用的方法列表

  2. 使用内置函数dir传入标识符/数据,可以查看对象内的所有属性及方法

提示: __方法名__ 格式的方法是 Python 提供的内置方法/属性,稍后会给大家介绍一些常用的 内置方法/属性

__doc__ 属性返回对象/函数的注释(三引号包围的注释)

序号 方法名 类型 作用
01 __new__ 方法 创建对象时,会被自动调用
02 __init__ 方法 对象被初始化时,会被自动调用
03 __del__ 方法 对象被从内存中销毁前,会被自动调用
04 __str__ 方法 返回对象的描述信息,print l 函数输出使用

当使用类名( ) 创建对象时,会自动执行以下操作

  1. 为对象在内存中分配空间 — 创建对象(create, 使用 __new__() 方法)
  2. 为对象的属性设置初始值 — 初始化方法(init,使用 __init__() 方法)

其中__new____init__的作用相当于 C++ 中的构造函数,__del__ 相当于析构函数。

__new__

new is static class method,

Use new when you need to control the creation of a new instance.

new is the first step of instance creation. It's called first, and is responsible for returning a new instance of your class.

__init__

init is instance method, new has to create the instance first, so init can initialize it.

Use init when you need to control initialization of a new instance.

init doesn't return anything; it's only responsible for initializing the instance after it's been created.

Note that init takes self as parameter. Until you create instance there is no self.

  • __init__ 是对象的内置方法,专门用来定义一个类具有哪些属性

  • __init__ 方法内部使用 self.属性名=属性的初始值 就可以定义属性

  • 定义属性之后,再使用 Cat 类创建的对象,都会拥有该属性

在开发中,如果希望在创建对象的同时,就设置对象的属性,可以对 __init__ 方法进行改造

  1. 把希望设置的属性值,定义成 __init__ 方法的参数
  2. 在方法内部使用 self.属性=形参 接收外部传递的参数
  3. 在创建对象时,使用类名(属性 1. 属性 2, ...) 调用

__del__

  • 在 Python 中

    • 当使用 类名() 创建对象时,为对象分配完空间后,自动调用 __init__方法
    • 当一个对象被从内存中销毁 前,会自动调用 __del__ 方法
  • 应用场景

    o __init__改造初始化方法,可以让创建对象更加灵活

    o __del__如果希望在对象被销毁前,再做一些事情,可以考虑一下__del__方法

__str__

__str__ 方法自定义变量信息, 注意该方法必须返回一个字符串

1
2
3
4
5
6
7
8
9
10
11
12
class Cat():
def __str__(self):
"""
return string
"""
return 'this is a class for test!'
...
tom = Cat()
print(tom)

output:
this is a class for test!

生命周期

  1. 调用 类名()后 , 自动调用类的 __new__() 方法,创建对象,生命周期开始

  2. 自动调用 __init__() 方法进行初始化(初始化属性等)

  3. 在对象的生命周期内,可以访问对象属性,或者让对象调用方法

  4. 局部变量(局部对象)的生命周期就是在函数内,函数执行完,自动调用 __del__ ,全局变量的生命周期是全局,程序运行结束,自动调用 __del__

  5. 一个对象的 __del__ 方法一旦被调用,生命周期结束

封装

  1. 封装是面向对象编程的一大特点
  2. 面向对象编程的第一步一-将属性和方法封装到一个抽象的类中
  3. 外界使用类创建对象,然后让对象调用方法
  4. 对象方法的细节都被封装在类的内部

定义没有初始值的属性

在定义属性时,如果不知道设置什么初始值,可以设置为 None

  • None 关键字表示什么都没有

  • 表示一个空对象,没有方法和属性,是一个特殊的常量

  • 可以将 None 值给任何一个变量

条件判断

当一个对象想要执行一个方法时,需要首先判断它有没有满足执行该方法的条件。

身份运算符

身份运算符用于比较两个对象的内存地址是否一致, 即:是否是对同一个对象的引用

  • 在 Python 中针对 None 比较时,建议使用 is 判断运算符描述实例
运算符 描述 实例
is is 是判断两个标识符是不是引用同一个对象 x is y, 类似 id (x) = id(y)
is not is not 是判断两个标识符是不是引用不同对象 x is not y, 类似 id (x)!= id(y)

is xisy,类似 is not: X Is not y,类似 ida) l=id ()

is 用于判断两个变量引用对象是否为同一个(即:内存地址是否一致)

== 用于判断引用变量的是否相等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In [5]: a=[1,2,3,4]

In [6]: a
Out[6]: [1, 2, 3, 4]

In [7]: id(a)
Out[7]: 4512288848

In [8]: b=[1,2,3,4]

In [9]: id(b)
Out[9]: 4514154608

In [10]: a == b
Out[10]: True

In [11]: a is b
Out[11]: False

In [12]: a is not b
Out[12]: True

私有属性和私有方法

应用场景及定义方式

应用场景

  • 在实际开发中,对象某些属性或方法可能只希望在对象的内部被使用,而不希望在外部被访问到

  • 私有属性就是对象不希望公开的属性

  • 私有方法就是对象不希望公开的方法

定义方式

  • 定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
1
2
3
4
5
6
7
8
class Women:
def __init__(self, name):
self.name = name
self.__age = 18

def __secret(self):
print(f"{self.name}'s age is {self.__age}")
...

伪私有属性和私有方法

提示:在日常开发中,不要使用这种方式、访问对象的私有属性或私有方法

Python 中,并没有真正意义私有

在给属性、方法命名时,实际是对名称做了一些特殊处理,使得外界无法访问到

处理方式:在名称前面加上_类名->_类名__名称, 即: [单下划线][类名][双下划线][名称]

1
2
print(xiaofang._Women__age)
xiaofang._Women__secret()

补充

id( object )

Return the identity of an object.

This is guaranteed to be unique among simultaneously existing objects. (CPython uses the object's memory address.)

del

The del keyword is used to delete objects. In Python everything is an object, so the del keyword can also be used to delete variables, lists, or parts of a list etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In [10]: li=[1,2,3]

In [11]: del li[1]

In [12]: li
Out[12]: [1, 3]

In [13]: del li

In [14]: li
------------------------------------------------------------------------mathjax: true
---NameError Traceback (most recent call last)
<ipython-input-14-3fab4c9c2cf3> in <module>
----> 1 li

NameError: name 'li' is not defined

print

使用 * 表示重复输出多次

1
print('-'*50)

一个对象的属性可以是另外一个类创建的对象

参考资料: Why is __init__() always called after __new__()?