Object-Oriented(面向对象)

14

Object-Oriented介绍

  面向对象是一种非常重要的编程思想,把数据和操作放在一起,作为一个整体,称为对象。Python的面向对象和C++类似,也具有面向对象的三大特点,封装,继承和多态。

面向过程与面向对象

面向过程的编程思想

  自上而下顺序执行,逐步求精。
  程序结构按照功能分为若干模块,各部分相对独立。
  每一模块内部均是由顺序,选择,循环三种基本结构。
  程序流程在写程序时就已经确定。

面向对象的编程思想

  把数据和操作放在一起,作为一个整体,称为对象。
  对同类对象抽象出其共性,形成类。
  类通过一个外部接口与外界操作。
  程序流程在用户使用时决定。

Python面向对象应用

Python创建类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 类就是一种物体的总称,具有属性(成员变量)和行为(成员方法)两个特征。其本身并不占用内存空间,其实例化的对象占内存空间。
# class 类名(父类):
# 属性
# 行为

# 类名一般首字母大写,object是所有类的父类,一般没有合适的父类就写object。
class Person(object):
# 定义属性
name = ''
age = 0
height = 0
weight = 0

# 定义行为,注意成员方法的参数一般以self当作第一个参数(可以为其他的单词,但是几乎都使用self),其中self就代表类的实例,哪个对象调用方法哪个对象就是self,类似于C/C++中的this指针。
def eat(self, food):
print('eat' + food)

def sleep(self):
print('I need sleep')

88

Python实例化对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person(object):
name = ''
age = 0
height = 0
weight = 0

def eat(self, food):
print('eat' + food)

def sleep(self):
print('I need sleep')

# 类似于女娲造人一样,有了人型模具,女娲可以按照模具创建人类对象
# 对象名 = 类名(参数列表) 用类名实例化对象,注意如果没有参数,也不能省略括号。
per = Person()
print(per)

89

Python访问对象属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Person(object):
name = ''
age = 0
height = 0
weight = 0

def eat(self, food):
print('eat ' + food)

def sleep(self):
print('I need sleep')

# 对象名.属性名 访问该对象的某一个属性,也可以通过这种方法对该对象的某一属性赋值
per = Person()
print(per.name + '的年龄为:' + str(per.age))
per.name, per.age = '张三', 18
print(per.name + '的年龄为:' + str(per.age))

90

Python访问对象方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person(object):
name = ''
age = 0
height = 0
weight = 0

def eat(self, food):
print('eat ' + food)

def sleep(self):
print('I need sleep')

# 对象名.方法名(参数列表) 访问该对象的某一个方法,注意self参数不需要传值
per = Person()
per.eat('apple')
per.sleep()

91

Python类的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# def __init__(self, 参数列表): 构造函数在使用类创建对象的时候自动调用,如果不显示的写出构造函数,默认自动添加一个空的构造函数
class Person(object):
def __init__(self, name, age, height, weight):
self.name = name
self.age = age
self.height = height
self.weight = weight

def eat(self, food):
print('eat ' + food)

def sleep(self):
print('I need sleep')

# 类名实例化对象时给对象的属性赋值
per = Person('李四', 20, 180, 140)
print(per.name + '的年龄为:' + str(per.age))

92

Python类的析构函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# def __del__(self): 析构函数在释放对象的时候自动调用,如果不显示的写出析构函数,默认自动添加一个空的析构函数
class Person(object):
def __del__(self):
print('Destroy the object')

def eat(self, food):
print('eat ' + food)

def sleep(self):
print('I need sleep')

# 类名实例化对象时给对象的属性赋值
per = Person()
del per

93

Python中类属性和对象属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person(object):
talent = None

def __init__(self, name, age):
self.name = name
self.age = age

# 类属性是写在类内部的属性,而对象属性是用self定义或者在外部动态定义的。
# 对象属性的优先级高于类属性,如果一个对象没有对象属性,则使用其类属性,如果添加了对象属性,则使用其对象属性。
# 在此代码中talent属于类属性,可以通过类名.属性调用,name和age属于对象属性,通过对象名.属性调用。
# 注意:尽量不要将对象属性与类属性同名,因为对象属性会屏蔽类属性,当删除对象属性后,又能使用类属性了。
per = Person('张三', 18)
print(Person.talent)
print(per.talent)
per.talent = 'Python'
print(Person.talent)
print(per.talent)

# 类方法和对象方法类似,类方法是在类内部的方法,而对象方式是在外部动态定义的方法,一般不常用,作为了解即可。

100

Python类打印函数

1
2
3
4
5
6
7
8
9
10
11
12
13
# def __str__(self): 在调用print打印对象时自动调用,是一个给用户使用的描述对象的方法,如果不显示的写出,默认返回类的名称和所处的内存地址
class Person(object):
def __init__(self, name, age, height, weight):
self.name = name
self.age = age
self.height = height
self.weight = weight

def __str__(self):
return "姓名:%s 年龄:%d,身高:%.1f,体重:%.1f" %(self.name, self.age, self.height, self.weight)

per = Person('王五', 21, 178, 160)
print(per)

94

Python动态语言

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Person(object):
def __init__(self, name, age, height, weight):
self.name = name
self.age = age
self.height = height
self.weight = weight

per = Person('赵六', 22, 186, 170)
print(per.name + '的存款为:' + str(per.money))

# per本来没有money属性,可以动态添加money属性
per.money = 10000
print(per.name + '的存款为:' + str(per.money))

# 还可以动态添加方法,需要从types中导入Method类
from types import MethodType

def say(self):
print('my name is ' + self.name)

per.say()

# 对象名.方法名 = MethodType(添加的函数名, 对象名)
per.say = MethodType(say, per)
per.say()

95

Python中动态添加限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from types import MethodType 

# 通过定义__slots__ = (成员属性或者成员方法名) 使对象中的成员必须存在于元组之中,可以限制对象随意动态添加成员
class Person(object):
__slots__ = ('name', 'age', 'money')

def __init__(self, name, age):
self.name = name
self.age = age

per = Person('赵六', 22)
per.money = 10000
print(per.name + '的存款为:' + str(per.money))
per.weight = 160

def say(self):
print('my name is ' + self.name)

per.say = MethodType(say, per)

101

Python类中的共有和私有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# __属性名/函数名 如果想让内部成员不被外部直接访问,在成员属性或方法前加__(两个下划线),但是在内部是可以使用的
# 如果想修改其值只能通过自定义一个函数,实现对某些成员变量进行修改操作,这样也达到了一种保护作用
class Person(object):
def __init__(self, name, age, height, weight):
self.name = name
self.age = age
self.height = height
self.__weight = weight

def set_weight(self, weight):
self.__weight = weight

def enquire(self):
print('体重为:' + str(self.__weight))

per = Person('王五', 21, 178, 160)
per.enquire()
print(per.__weight)
per.set_weight(150)
per.enquire()

# 原因是Python解释器将__成员变成了_(一个下划线)类名__(两个下划线)成员名(即在此将__weight改成了_Person__weight),因此不是绝对私有的
print(per._Person__weight)

96

Python类中的@property装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 对私有成员想要便捷的访问和修改可以使用@property装饰器,相当于调用了get和set方法,可以让受限制的成员也能够直接使用.语法
# @property
# def 变量名(self):
# return self.__变量名
# @变量名.setter
# def 变量名(self, 变量名):
# xxx
# 以上变量名都是未加下划线的变量名,@property下面的内容相当于get方法,@变量名.setter下面的内容相当于set方法。

class Person(object):
def __init__(self, name, age, height, weight):
self.name = name
self.age = age
self.height = height
self.__weight = weight

def set_weight(self, weight):
self.__weight = weight

@property
def weight(self):
return self.__weight
@weight.setter
def weight(self, weight):
self.__weight = weight

per = Person('王五', 21, 178, 160)

# 调用时也是直接调用对象名.原名即可,不需要加双下划线__
print(per.weight)
per.weight = 150
print(per.weight)

# 原因是Python解释器将__成员变成了_(一个下划线)类名__(两个下划线)成员名(即在此将__weight改成了_Person__weight),因此不是绝对私有的
print(per._Person__weight)

96

Python类的单继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Person(object):
def __init__(self, name, age, height, weight):
self.name = name
self.age = age
self.height = height
self.weight = weight

def eat(self, food):
print('eat ' + food)

def sleep(self):
print('I need sleep')

# 对于世间万物,大多数都有这一般和特殊的关系,如人和程序员之间的关系,程序员继承了人的所有特点,但是又有一些特殊的特点。将人这个类别称为子类(基类),将程序员这个类别称为父类(超类)。
# 所有的类都是继承于object类,继承可以大大简化代码,提高代码的健壮性和安全性。
# class 类名(父类): 子类继承父类,需要在类名后面的括号中写入父类名,继承时调用父类的__init__只需要写super(子类名, self).__init__(参数列表)即可,参数列表中不需要写self
# 注意父类的私有成员子类可以继承过来,但是无法直接使用,只能通过父类的自定义函数访问。
# 子类特有的成员和之前定义普通类时相同
class Programmer(Person):
def __init__(self, name, age, height, weight, language):
super(Programmer, self).__init__(name, age, height, weight)
self.language = language

pro = Programmer('钱七', 23, 181, 135, 'Python')
pro.eat('watermelon')
print(pro.language)

97

Python类的多继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Father(object):
def __init__(self, name, age, talent):
self.name = name
self.age = age
self.talent = talent

def play(self):
print('play computer games')

def sleep(self):
print('Father need sleep')

class Mother(object):
def __init__(self, name, age, beauty):
self.name = name
self.age = age
self.beauty = beauty

def shopping(self):
print('go shopping')

def sleep(self):
print('Mother need sleep')

# 除了单继承外也有多继承的情况,比如遗传就是一种典型的多继承,孩子要继承父亲和母亲的特点
# class 类名(父类): 子类继承父类,如果需要多继承,则在类名后面的括号中写入多个父类名
# 继承时构造函数中调用父类的__init__,只需要写父类名.__init__(self, 参数列表)即可使用,注意要写self
# 注意父类中方法名相同,默认调用的是在括号中排在前面的父类中的方法
class Child(Father, Mother):
def __init__(self, name, age, talent, beauty):
Father.__init__(self, name, age, talent)
Mother.__init__(self, name, age, beauty)

chi = Child('辛巴', 22, 'Python', 99)
print(chi.name + '的年龄为:' + str(chi.age))
print('我的才能是:' + chi.talent)
print('我的颜值是:' + str(chi.beauty))
chi.play()
chi.shopping()
chi.sleep()

98

Python类的多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Animal(object):
def __init__(self, name):
self.name = name

def eat(self, food):
print(self.name + ' eat ' + food)

class Cat(Animal):
def __init__(self, name):
super(Cat, self).__init__(name)

class Mouse(Animal):
def __init__(self, name):
super(Mouse, self).__init__(name)

class Person(object):
def feed(self, animal, food):
animal.eat(food)

# 对于继承自同一类的多个类具有多态的性质,即子类有多种表现形态
# 此代码中动物类就是父类,猫类和老鼠类都继承自动物类,所以猫类和鼠类都有父类的方法
# 因此传入不同的子类对象具有不同的表现形态

per = Person()
tom = Cat('Tom')
jerry = Mouse('Jerry')
per.feed(tom, 'fish')
per.feed(jerry, 'rice')

99

Python运算符重载

109

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 为了使运算方便,有时需要进行运算符重载,典型的就是字符串的相加,1 + 2 = 3,但是字符串相加就是字符串的连接。
# 说明对字符串的加法进行了重新定义,使其可以完成相加操作。同理,对自己写的类也可以进行运算符重载,使两个类可以做运算。
# 要重载什么操作就查操作对应的特殊函数,然后将其重载即可。

class Person(object):
def __init__(self, money):
self.money = money

def __add__(self, other):
return Person(self.money + other.money)

def __str__(self):
return 'money:' + str(self.money)

# 此代码重载了加法运算符和打印操作
per1 = Person(100)
print(per1)
per2 = Person(200)
print(per2)
per3 = per1 + per2
print(per3)

103

Object-Oriented小结

  Object-Oriented面向对象是计算机语言中一种重要的思想,它的出现将程序员从一个执行者变成了一个管理者,程序员在使用时只需要知道能做什么,而不需要知道具体如何实现,而且每次创建对象时只需要一行代码,调用某一函数时也不需要关心内部的结构,大大减少了阅读代码的时间和内存的占用情况。因此面向过程是程序员的必经之路,需要熟练的掌握。

-------------本文结束感谢您的阅读-------------
0%