Python面向对象

Posted 博小园

tags:

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

类是对一群具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用,特征被称为属性,行为被称为方法,类就相当于制造飞机时的图纸,是一个模板,是负责创建对象的。

对象是由类创建出来的一个具体存在,可以直接使用,由哪个类创建出来的对象,就拥有在那个类中定义的属性和方法,对象就相当于用图纸制造的飞机,在程序开发中,先有类,然后再有对象。

1.创建类和对象

 1 #创建类:class为创建类的关键字,Dog为类名,self为方法的特殊参数,必填
 2 class Dog:
 3     #类中定义的函数为方法
 4     def eat(self):
 5         print("狗吃饭")
 6     def run(self):
 7         print("狗奔跑")
 8 
 9 #根据Dog类创建对象dog
10 dog = Dog()

说明:

1.类名表示一类事物的名字,满足大驼峰命名法(每一个单词的首字母大写,单词与单词质检没有下划线);属性表示一类事物具有什么样的特征;方法表示一类事物具有什么样的行为。

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

1 def demo():
2     pass
3 
4 
5 print(dir(demo))
6 
7 -------输出结果--------
8 [__annotations__, __call__, __class__, __closure__, __code__, __defaults__, __delattr__, __dict__, __dir__, __doc__, __eq__, __format__, __ge__, __get__, __getattribute__, __globals__, __gt__, __hash__, __init__, __kwdefaults__, __le__, __lt__, __module__, __name__, __ne__, __new__, __qualname__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__]

3.Python中self表示当前对象,当前正在操作的对象,而不是当前类,当某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以我们只需要传递后面的参数即可。

1 class Person: 
2     
3     def eat(self):  # 类中所有def定义的方法,参数都要带self,而且要放在第一位
4         print("人吃饭......")
5 
6 
7 person = Person()
8 person.eat()

4.当使用类名()创建对象时,会自动执行以下操作:为对象在内存中分配空间,即创建对象;为对象的属性设置初始值,即调用初始化方法,这个初始化方法就是__init__方法,该方法是对象的内置方法。

__init__方法是专门用来定义一个类具有哪些属性的方法,在__init__方法内部使用self.属性名=属性的初始值,就可以定义属性,定义属性后,再使用类创建的对象,都会拥有该属性。

 1 class Person:
 2 
 3     def __init__(self, name, age):
 4         self.name = name
 5         self.age = age
 6         
 7     def eat(self):
 8         print("%s 吃饭" % self.name)
 9 
10 
11 person = Person("张三", 18)
12 person.eat()

5.内置方法__del__(对象被从内存中销毁前,该方法会被自动调用)和__str__(返回对象的描述信息,print函数输出使用)。

6.在定义属性或者方法时,在属性或者方法名前增加两个下划线,定义的就是私有属性或者方法。

在Python中并没有真正意义上的私有,在给属性,方法命名时,实际是对名称做了一些特殊处理,使得外界无法访问到,可以在所有属性或者方法前面加上_类名,即_类名__名称访问私有属性或者方法。

 1 class Person:
 2 
 3     def __init__(self, name, age):
 4         self.name = name
 5         self.age = age
 6 
 7     def eat(self):
 8         print("%s 吃饭" % self.name)
 9 
10     def __jump(self):
11         print("%s 跳舞" % self.name)
12 
13 
14 person = Person("张三", 18)
15 person.eat()
16 # person.__jump() 报错
17 person._Person__jump()

7.类的成员包括字段(普通字段,静态字段),方法(普通方法,类方法,静态方法)和属性(普通属性),其中只有普通字段的内容保存在对象中,而其他的成员,则都是保存在类中。

字段

字段分为普通字段和静态字段,他们的区别主要是在内存中保存的位置不同,普通字段属于对象,静态字段属于类。

 1 class Province:
 2     country = "中国"  # 静态字段
 3 
 4     def __init__(self, name):
 5         self.name = name  # 普通字段
 6 
 7 
 8 province = Province("山东省")
 9 print(province.name)
10 print(Province.country)

普通字段通过对象访问,静态字段通过类可以直接访问。

方法

方法包括普通方法,静态方法和类方法,三个方法在内存中都属于类。

  • 普通方法:由对象调用,至少有一个self参数,当对象调用方法时自动把对象赋值给self。
  • 类方法:由类调用,至少一个cls参数,当调用方法时自动把类赋值给cls。
  • 静态方法:由类调用,无默认参数。
 1 class Demo:
 2 
 3     def ord_func(self):
 4         print("普通方法")
 5 
 6     @classmethod
 7     def class_method(cls):
 8         print("类方法")
 9 
10     @staticmethod
11     def static_method():
12         print("静态方法")
13 
14 
15 demo = Demo()
16 demo.ord_func()  # 调用普通方法
17 Demo.class_method()  # 调用类方法
18 Demo.static_method()  # 调用静态方法

属性

1 class Demo:
2     # 定义属性
3     @property
4     def f(self):
5         return "boxiaoyuan"
6 
7 
8 demo = Demo()
9 print(demo.f)  # 调用属性

在定义属性时,只需要在普通方法的基础上添加@property即可,属性只有一个参数self。

Python的类有经典类(Python2)和新式类(Python3),新式类的属性有三种访问方式,即@property,@方法名.setter,@方法名.deleter,经典类只有一种,即在普通方法上增加@property。

 1 class Person:
 2 
 3     @property
 4     def sick(self):
 5         return "有病了"
 6 
 7     @sick.setter
 8     def sick(self, value):
 9         print(value)
10 
11     @sick.deleter
12     def sick(self):
13         print("deleter")
14 
15 
16 person = Person()
17 print(person.sick)
18 person.sick = "有病"
19 del person.sick

2.面向对象的三大特性

1)封装:把内容封装起来,然后进行调用

 1 class Dog:
 2     def __init__(self,name,age):
 3         self.name=name
 4         self.age=age
 5     def eat(self):
 6         print("狗吃饭")
 7     def run(self):
 8         print("狗奔跑")
 9     def display(self):
10         print(self.name)
11         print(self.age)
12 
13 
14 dog=Dog(boxiaoyuan,15)
15 print(dog.name)
16 print(dog.age)
17 dog.display()
18 
19 -------输出结果------
20 boxiaoyuan
21 15
22 boxiaoyuan
23 15

注:对于面向对象的封装来说,就是把内容通过构造函数封装到对象中,然后通过对象直接调用或者使用self间接调用。

2)继承:实现代码的重用,相同的代码不需要重复的编写。

继承的概念:子类拥有父类的所有方法和属性。

子类继承父类,可以直接享受父类中已经封装好的方法,子类中应该根据职责,封装子类特有的属性和方法。

 1 class Animal:
 2     def eat(self):
 3         print("吃东西")
 4 
 5     def drink(self):
 6         pass
 7 
 8     def run(self):
 9         pass
10 
11 
12 class Dog(Animal):
13     def dark(self):
14         print("狗叫")
15 
16 
17 dog = Dog()
18 dog.eat()
19 dog.dark()

当父类的方法实现不能满足子类需求时,可以对方法进行重写(override)。

 1 class Animal:
 2     def eat(self):
 3         print("吃东西")
 4 
 5     def drink(self):
 6         pass
 7 
 8     def run(self):
 9         pass
10 
11 
12 class Dog(Animal):
13     def dark(self):
14         print("狗叫")
15     
16     def run(self):
17         print("狗跑的很快呀")
18 
19 
20 dog = Dog()
21 dog.eat()
22 dog.dark()

如果子类的方法实现中包含父类的方法实现,即父类原本封装的方法实现是子类方法的一部分,可以使用super().父类方法来调用父类方法。

在Python中super是一个特殊的类,super()就是使用super类创建出来的对象,最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现。

 1 class Animal:
 2     def eat(self):
 3         print("吃东西")
 4 
 5     def drink(self):
 6         pass
 7 
 8     def run(self):
 9         print("")
10 
11 
12 class Dog(Animal):
13     def dark(self):
14         print("狗叫")
15 
16     def run(self):
17         super().run()
18         print("狗跑的很快呀")
19 
20 
21 dog = Dog()
22 dog.run()

子类对象不能在自己的方法内部直接访问父类的私有属性和私有方法,但是子类对象可以通过父类的公有方法间接访问私有属性和私有方法。

 1 class A:
 2     def __init__(self):
 3         self.__num = 12
 4         self.num2 = 14
 5 
 6     def __test(self):
 7         print("父类私有方法")
 8 
 9     def test(self):
10         print(self.__num)
11         self.__test()
12 
13 
14 class B(A):
15     def sub_test(self):
16         self.test()
17 
18 
19 b = B()
20 b.sub_test()

说明:子类不重写__init__,实例化子类时,会自动调用父类定义的__init__方法,但是子类重写了__init__时,实例化子类时,就不会调用父类已经定义的__init__。

 Python的类可以继承多个类,当Python的类继承了多个类时,其寻找方法的方式有两种,分别是:深度优先广度优先

当类是经典类时,多继承情况下,会按照深度优先的方式查找;当类是新式类时,多继承情况下,会按照广度优先的方式查找。如果当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

1 class A:  # A是经典类
2     pass
3 
4 
5 class B(A):  # B是经典类
6     pass
1 class A(object):  # A是新式类
2     pass
3 
4 
5 class B(A):  # B是新式类
6     pass
 1 class D:
 2     def f(self):
 3         print("D---f()")
 4 
 5 
 6 class C(D):
 7     def f(self):
 8         print("C---f()")
 9 
10 
11 class B(D):
12     def f(self):
13         print("B---f()")
14 
15 
16 class A(B, C):
17     def f(self):
18         print("A---f()")
19 
20 
21 a = A()
22 a.f()

在执行f方法时,首先在A类中查找方法f,如果A类中没有,则继续去B中查找,如果B中没有,则继续去D类中查找,如果D类中没有,则继续去C类中查找,如果仍然没有找到,则报错。所以查找的顺序为A--B--D--C,另外,在查找f方法的过程中,一旦找到,就会终止,不会继续查找。

 1 class D(object):
 2     def f(self):
 3         print("D---f()")
 4 
 5 
 6 class C(D):
 7     def f(self):
 8         print("C---f()")
 9 
10 
11 class B(D):
12     def f(self):
13         print("B---f()")
14 
15 
16 class A(B, C):
17     def f(self):
18         print("A---f()")
19 
20 
21 a = A()
22 a.f()

在执行f方法时,首先在A类中查找方法f,如果A类中没有,则继续去B中查找,如果B中没有,则继续去C类中查找,如果C类中没有,则继续去D类中查找,如果仍然没有找到,则报错。所以查找的顺序为A--B--C--D,另外,在查找f方法的过程中,一旦找到,就会终止,不会继续查找。

在Python3中,所有的类默认继承object,即所有的类都是新式类。

在Python2中,类默认不继承object,只要不写object,所有该类和子类均为经典类。

 3)多态:不同的子类调用相同的方法,产生不同的结果。

 1 class D:
 2     pass
 3 
 4 
 5 class B(D):
 6     def f(self):
 7         print("B---f()")
 8 
 9 
10 class A(D):
11     def f(self):
12         print("A---f()")
13 
14 
15 def Func(obj):
16     obj.f()
17 
18 
19 a = A()
20 Func(a)
21 
22 b = B()
23 Func(b)

 

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

python之路之前没搞明白4面向对象(封装)

Python面向对象学习之八,装饰器

python:第二部分:面向对象:面向对象object orinted

Python 面向对象

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

面向对象编程其实很简单——Python 面向对象(初级篇)