17.python面向对象

Posted 大道至简

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了17.python面向对象相关的知识,希望对你有一定的参考价值。

面向对象的编程(object oriented programming),简称OOP:是一种编程的思想。OOP把对象当成一个程序的基本单元,一个对象包含了数据和操作数据的函数。面向对象的出现极大的提高了编程的效率,使其编程的重用性增高。

模拟场景理解面向对象和面向过程:

 1 ‘‘‘
 2 使用面向过程的思想解决吃饭的问题?
 3         步骤:
 4         1).思考今天吃什么?
 5         2).去买菜(货比三家)
 6         3).摘菜
 7         4).洗菜
 8         5).切菜
 9         6).炒菜
10         7).焖饭
11         8).吃饭
12         9).洗刷
13 使用面向对象的思想解决吃饭的问题?
14         步骤:
15         1).思考今天吃什么?
16         2).去饭店
17             ①.调用服务员的点菜功能
18             ②.将菜品告知后台大厨
19             ③.大厨调用服务员的上菜功能
20         3).开始吃饭
21         4).结账走人(多种支付方式)
22 ‘‘‘

Python是解释性语言,但是它是面向对象的,能够进行对象编程。面向对象是一种编程方式,此编程方式的实现是基于对  和 对象 的使用;类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中);对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数。大白话理解类和对象的区别:i类:具有一些列相同特征、行为的"事物",它的表现是不具体的、不清晰的、模糊的概念;对象:从类中实例化得到,一个实实在在的个体,在内存中有体现;它的表现是具体的、清晰的、看得见摸的着的。

遇到面向对象的问题,通常可以考虑如下三个环节:

  1). 设计类,定义属性、函数、...(可能需要花费大量的时间) ;

  2). 创建(实例化)对象(简单,一行代码搞定,但是内存比较复杂);

  3). 对象调用属性或者函数完成需求。

 1 # 1.设计类
 2 class Car(object): 
 3      
 4     # 属性
 5     color = "红色"
 6     brand = "BMW"
 7     number = "沪A88888"
 8 
 9     # 函数/方法
10     def run(self):
11         print(%s的%s,车牌为%s,正在飞速的行驶... %(self.color,self.brand,self.number))
12 
13     def stop(self):
14         print(车停了...)
15 
16 # 2.创建对象/实例化对象
17 c1 = Car()
18 print(c1,type(c1))                  # 得到<__main__.Car object at 0x000000000220D710> <class ‘__main__.Car‘>
19 
20 # 3.对象调用属性
21 print(c1.color,c1.brand,c1.number)  # 红色 BMW 沪A88888
22 
23 # 4.对象调用函数
24 c1.run()                            # 红色的BMW,车牌为沪A88888,正在飞速的行驶...
25 c1.stop()                           # 车停了...
26 
27 # 创建第二个对象
28 c2 = Car()
29 print(c2,type(c2))                  # 得到<__main__.Car object at 0x000000000272D7B8> <class ‘__main__.Car‘>
30 
31 print(c1 == c2)                     # 得到False ,比较的是地址,c1和c2的地址不一样
32 
33 c2.color = "白色"
34 c2.brand = "BYD"
35 c2.number = "京A66666"
36 print(c2.color,c2.brand,c2.number)   # 白色 BYD 京A66666
37 print(c1.color,c1.brand,c1.number)   # 红色 BMW 沪A88888
38 ‘‘‘在一个模块中可以创建多个对象,它们彼此之间是相互独立存在(堆空间有体现),切互不干扰...‘‘‘
39 
40 c3 = c1                              # c1和c3的地址是一样的,共用,c1不调用了,但c3还指在堆上,c1记录的地址又给到c3一份
41 c1 = None
42 ‘‘‘此时堆中有1个空间,不存在垃圾空间;因为c1虽然被赋值为None了,但是c3仍然记录了堆中对象空间的地址(维护这层关系)‘‘‘

 

类的成员:

1). 字段:普通字段、静态字段

普通字段需要通过对象来访问,而静态字段通过类访问,在使用上可以看出普通字段和静态字段的归属是不同的;他们的本质的区别是内存中保存的位置不同,普通字段属于对象,而静态字段属于类;静态字段在内存中只保存一份,普通字段在每个对象中都要保存一份;通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段。

 1 class Province:
 2 
 3     # 静态字段/类属性
 4     country = 中国
 5 
 6     def __init__(self, name):
 7         # 普通字段/对象属性
 8         self.name = name
 9 
10 # 实例对象obj1
11 obj1 = Province(河北省)
12 print(obj.name)   # 直接访问普通字段
13 
14 # 实例对象obj2
15 obj2 = Province(河南省)
16 print(obj.name)   # 直接访问普通字段
17 
18 # 直接访问静态字段
19 Province.country

 

2). 方法:普通方法、类方法、静态方法、属性方法

前三种方法在内存中都归属于类,区别在于调用方式不同。普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;类方法:由类调用;至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;静态方法:由类调用;无默认参数。

相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份;不同点:方法调用者不同、调用方法时自动传入的参数不同。

静态方法意思是把 @staticmethod 下面的函数和所属的类截断了,这个函数就不属于这个类了,没有类的属性了,只不是还是要通过类名的方式调用  ,把静态方法当作一个独立的函数给他传参就行了。

类方法只能访问类变量,不能访问实例变量。

属性方法把一个方法变成一个静态属性,属性就不用加小括号那样的去调用了

 1 class Foo:
 2 
 3     def __init__(self, name):
 4         self.name = name
 5 
 6     def ord_func(self):
 7         """ 定义普通方法,至少有一个self参数 """
 8         print(普通方法)
 9 
10     @classmethod
11     def class_func(cls):
12         """ 定义类方法,至少有一个cls参数 """
13         print(类方法)
14 
15     @staticmethod
16     def static_func():
17         """ 定义静态方法 ,无默认参数"""
18         print(静态方法)
19 
20 # 调用普通方法
21 f = Foo()
22 f.ord_func()
23 
24 # 调用类方法
25 Foo.class_func()
26 
27 # 调用静态方法
28 Foo.static_func()

属性方法:其实是方法里面普通方法的变种。属性方法的定义和调用要注意:定义时,在普通方法的基础上添加 @property 装饰器;定义时,属性仅有一个self参数调用时,无需括号。补充:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象,属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。Python的属性的功能是:属性内部进行一系列的逻辑计算,最终将计算结果返回。

 1 class Foo:
 2 
 3    # 定义普通方法
 4    def func(self):
 5        pass
 6 
 7    # 定义属性
 8    @property
 9    def prop(self):
10        pass
11 
12 # 实例化对象
13 foo_obj = Foo()
14 
15 foo_obj.func() # 调用普通方法
16 foo_obj.prop   # 调用属性方法

属性方法的两种定义方式:装饰器 即:在方法上应用装饰器;静态字段 即:在类中定义值为property对象的静态字段。

 1 # 装饰器方式:在类的普通方法上应用@property装饰器
 2 class Goods:
 3 
 4     @property
 5     def price(self):
 6         return "wupeiqi"
 7 
 8 obj = Goods()
 9 
10 obj.price  # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
11 
12 
13 # 静态字段方式,创建值为property对象的静态字段
14 class Foo:
15 
16     def get_bar(self):
17         return wupeiqi
18 
19     BAR = property(get_bar)
20 
21 obj = Foo()
22 
23 obj.BAR   # 自动调用get_bar方法,并获取方法的返回值

 

类特殊成员:

魔术函数:__开头并且__结尾的函数,我们称为魔术函数;特点:调用执行都不需要程序员关注,系统自行决定;例如:__init__、__del__、__str__ 、......  构造函数,析构函数,  重写函数,...... 

构造函数(constructor):又称构造方法/构造器,在生成对象时调用,一个对象只会被执行一次,可以用来进行一些初始化操作,不需要显示去调用,系统会默认去执行。

格式:__init__(self):

执行时机:在创建对象时被执行

 1 class Person(object):
 2 
 3     def __init__(self,name,age):
 4         self.name = name     
 5         self.age = age
 6         self.address = ‘中国‘
6 7 def details(self): 8 print(‘姓名为:%s,年龄为:%d,籍贯是:%s‘ %(self.name,self.age,self.address)) 9 10 # 创建对象 11 p1 = Person("多多",18) # 构造方法,通过类创建对象时,自动触发执行 12 # 创建第二个对象,与p1互不干扰,共同存在与堆中 13 p2 = Person("老王",28) 14 p2.details()

析构函数:当对象在内存中被释放时,自动触发执行,此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。这个方法默认是不需要写的,不写的时候,默认是不做任何操作的。因为不知道对象是在什么时候被垃圾回收掉,所以,除非确实要在这里面做某些操作,不然不要自定义这个方法。

格式:__del__(self):

执行时机:在程序结束前,将对象回收,清出内存

 1 class Dog:
 2 
 3     def __init__(self,name,age,color):
 4         print(我是构造函数...)
 5         self.name = name      
 6         self.age = age
 7         self.color = color
 8 
 9     def __del__(self):
10         print(我是析构函数...)
11     
12     def func(self):
13         print(我是func函数...)

__str__(self)函数:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值

对象实例化之后将数据给到对象名,此时如果打印对象名,在控制台上我们看到的是整个对象的类型以及在内存中的地址(十六进制),但是我们在开发过程中,对于类型和地址并不关注;我们更希望看到的是对象的各个属性内容,此时我们可以自己重新定义__str__(self)函数的函数体(就是函数重写),此函数有返回值,return后面的内容必须是str类型

执行时机:在打印对象名/引用名时被触发

 1 # 没有定义__str__方法时,打印创建的对象
 2 class Person(object):
 3 
 4     def __init__(self,name,age,address):
 5         self.name = name
 6         self.age = age
 7         self.address = address
 8 
 9 p = Person(韩梅梅,20,上海)
10 print(p)          # <__main__.Person object at 0x0000000004C3D978>
11 
12 
13 # 有定义__str__方法时,打印创建的对象
14 class Person(object):
15 
16     def __init__(self,name,age,address):
17         self.name = name
18         self.age = age
19         self.address = address
20 
21     def __str__(self):
22         return 姓名为:%s,年龄为:%d,籍贯是:%s人 %(self.name,self.age,self.address)   # return后面必须是字符串数据
23 
24 p = Person(韩梅梅,20,上海)
25 print(p)          # 姓名为:韩梅梅,年龄为:20,籍贯是:上海人

 

以上是关于17.python面向对象的主要内容,如果未能解决你的问题,请参考以下文章

Python学习:17.Python面向对象(属性(特性),成员修饰符,类的特殊成员)

17.python面向对象

17.Python面向对象之:类空间问题以及类之间的关系

day29 面向对象入门

面向面试编程代码片段之GC

PHP面向对象之选择工厂和更新工厂