Python面向对象:一篇文章掌握面向对象的基础
Posted 晚风Adore
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python面向对象:一篇文章掌握面向对象的基础相关的知识,希望对你有一定的参考价值。
Python 面向对象
一、面向对象简介
面向对象编程(object driented programming,OOP):是一种编程思路,也是Python语言的一个重要特点。将数据与函数绑定在一起,进行封装,这样能够更快速的开发程序,减少了重写代码的过程。
面向过程:就是我们一开始学习的,按照解决问题的步骤去写代码
二、类和对象的概念
类是具有一组相同或者相似特征(属性)和行为(方法)的一系列对象。对象是类的具体示例。
比如手机是一个类,华为,苹果,小米是对象(实例),有屏幕尺寸、处理器、分辨率等属性,开机、关机、拍照等行为(方法)。
类的定义
class 类名(object):
属性...
方法...
class Person(object): # (object)可省略
name = ''
age = 0
def eat(self):
print('Person类执行eat函数')
pass
创建对象
对象名 = 类名()
LiMing = Person()
LiMing.name = 'LiMing'
LiMing.age = 19
print('Liming name:',LiMing.name)
print('Liming age: ',LiMing.age)
LiMing.eat()
'''
Liming name: LiMing
Liming age: 19
Person类执行eat函数
'''
三、定义类的属性
普通(公开)属性
普通属性可以在类的外部直接访问
class A:
name = 'ssd'
age = 12
a1 = A()
print(a1.name,a1.age)
'''
ssd 12
'''
实例属性
实例化时才有的属性(使用__init__方法定义),因此通过类访问实例属性会报错找不到
class Animal:
name = 'default' # 类属性
def __init__(self,color):
#实例化时调用__init__,故color为实例属性
self.color = color
return
pass
dog1 = Animal('pink') #实例对象
print(dog1.name,dog1.color) # 实例对象访问类属性个实例属性
print(Animal.name)
# 类属性访问类属性
print(Animal.color)
# 类属性访问实例属性,报错,找不到实例属性,因为不进行实例化就不执行__init__就没有color属性
私有化属性
- 将属性定义为私有属性,不能在类的外部直接访问和修改,
- 同时其子类也不能继承该属性
- 可以防止被随意修改或意外修改
语法:
class A:
name = 'asd' #普通属性
__age = 16 #私有化属性,在变量前面加双下划线
若此时创建一个A类的对象,直接访问age变量,会报错显示找不到
a1 = A()
print(a1.__age)
因此要在要访问私有属性就要从类的内部,即使用类的实例化方法
class A:
name = 'asd' #普通属性
__age = 16 #私有化属性,在变量前面加双下划线
def getAge(self):
return self.__age
a2 = A()
print(a2.getAge()) # 调用类中的实例方法来访问私有属性
被保护的属性
- 将属性定义为被保护的属性,不能在类的外部直接访问和修改,
- 其子类可以继承该属性
- 可以防止被随意修改或意外修改
语法:
- List item
class A:
_name = 'asf' # 在变量前加单下划线
四、定义类的方法
实例方法
实例化对象后可以使用的方法,默认参数为self,指代本身
class A:
name = 'sdf'
def PrintName(self):
print(self.name)
return
a1 = A()
a1.PrintName()
类方法
用@classmethod 修饰,默认参数为cls,表示该类,
- 不需要实例化对象就能使用
- 可以用来修改类属性
- 每一个类方法上面都要添加一行@classmethod修饰
- 实例对象也可以调用
class Student:
country = 'China'
age = 19
@classmethod
def getCountry(cls):
return cls.country # 访问类属性
@classmethod
def getAge(cls):
return cls.age
xm = Student()
print(Student.getAge(),Student.getCountry())
print(xm.getAge())
'''
19 China
19
'''
静态方法
用@staticmethod修饰,默认没有参数
- 由于静态方法主要存放逻辑性代码,本身与类和对象没有交互.
- 使用静态方法可以节省内存资源,比如显示当前时间
- 实例对象也可以调用
import time # 导入Time模板
class T:
def showTimeNow():
# 功能独立,与类和对象无关
return time.strftime('%H:%M:%S',time.localtime())
t1 = T()
print(T.showTimeNow())
print(t1.showTimeNow())
私有化方法
- 不能在类的外部直接调用
- 同时其子类也不能继承该属性
语法:在方法前加__
def __func(self):
return
保护的方法
- 不能在类的外部直接调用
- 其子类可以继承该属性
语法:在方法前加_
def _func(self):
return
五、魔术方法
在Python中,有一些内置好的特定方法在特定的操作时会被调用,这些方法称之为魔术方法。常用的魔术方法有:__ new __ 、__ init __ 、__ str __ 、__ del __
1、__ new __ 创建对象实例
创建对象实例,每调用一次就会生成一个新的对象,可以不定义。
- cls是class的缩写,代表类名
- 需要返回对象类型object.__ new __(cls)才能创建成功(object. __ new __(cls)可以理解为object是一个空对象,在该对象使用 __ new __方法表明这个对象时cls类的,然后用return返回)
- 可以控制创建对象的一些属性限定,经常用来做单例模式的时候使用
class A:
def __new__(cls, *args, **kwargs):
print('执行__new__()')
return object.__new__(cls) #返回创建的实例化对象
2、__ init __实例对象初始化
- init可以带参数,并在创建对象时进行赋值
- 初始化方法创建实例对象时自动执行
ObjectName = ClassName(参数1,参数2,...)
class Person:
def __init__(self,Name):
self.name = Name
return
def eat(self): # 实例方法eat()
print("吃饭")
return
xm = Person('aaw')
xm.age = 12 # 追加实例属性,在类中可以不用定义
print(xm.name,xm.age)
'''
aaw 12
'''
3、__ str __ 打印对象的属性
返回字符串,打印对象时即打印返回的字符串,一般用于查看对象的属性
class A:
def __init__(self):
self.name = 'ssd'
self.age = 23
return
def __str__(self):
return 'Name:%s Age :%d'%(self.name,self.age)
a1 = A()
print(a1)
'''
Name:ssd Age :23
'''
4、__ del __ 释放对象
- 析构方法,释放类,在程序运行结束时自动调用
- 当对象被手动销毁(del 对象名)时也会自动调用__del__
- 析构函数一般用于资源回收,利用该方法销毁对象回收内存等资源
class A:
def __init__(self):
self.name = 'ssd'
self.age = 23
return
def __str__(self):
return 'Name:%s Age :%d'%(self.name,self.age)
def __del__(self):
print('释放')
return
a1 = A()
print(a1)
'''
Name:ssd Age :23
释放
'''
六、继承
单继承
子类继承父类,子类中包含父类所有的属性和方法,而父类不一定有子类中的属性和方法。
父类就是将不同类的共同属性和方法封装在一个类中,然后这些不同的类都继承父类即可使用共同的属性和方法,提高开发效率
class Animal:
def eat(self):
print("Animal Eat")
return
def drink(self):
print("Animal Drink")
return
class Cat(Animal): # 继承Animal类
def shout(self):
print('喵~喵~')
return
class Dog(Animal): # 继承Animal类
def shout(self):
print("汪!汪!")
return
cat1 = Cat()
dog1 = Dog()
cat1.eat()
cat1.shout()
dog1.drink()
dog1.shout()
'''
Animal Eat
喵~喵~
Animal Drink
汪!汪!
'''
多继承
一个子类也可以继承多个父类,同时 拥有多个父类所有的属性和方法
class A:
a1 = 'A类的属性a1'
def func(self):
print(self.a1)
print('执行A类的方法funcA')
return
pass
class B:
b1 = 'B类的属性b1'
def func(self):
print(self.b1)
print('执行B类的方法funcB')
return
pass
class C(A,B): # 多继承,继承A,B类
def funcC(self):
self.func()
self.func()
return
pass
cc = C()
cc.funcC()
如果同级父类有相同的方法,子类执行方法则根据继承的顺序优先选择。如果是不同级父类则优先会执行距离子类级数最少的类的方法(往上一级一级查找父类)(这里也算子类重写父类方法,子类的方法覆盖了父类的方法)
调用父类方法
语法:
父类类名.父类方法名()
super().父类方法名()# 自动找到父类并调用
如果继承多个父类,按照继承顺序去调用
重写父类方法
父类的方法不满足子类的需要,要去完善方法。
class A:
def Print(self):
print('执行A类的Print方法')
return
class B(A):
def Print(self):
print('执行B类的Print方法')
return
b1 = B()
b1.Print()
'''
执行B类的Print方法
'''
__ init __的重写
class Cat:
def __init__(self):
self.name = 'csy'
self.color = 'white'
return
pass
class DuanMaoCat(Cat):
def __init__(self):
return
pass
dm = DuanMaoCat()
print(dm.name)
# AttributeError: 'DuanMaoCat' object has no attribute 'name'
多态
多种状态、形态。同一方法对于不同的子类有不同的表现
实现多态需要满足条件:
- 需要有继承:多态发生在父类和子类之间。
- 方法重写:不同子类重写父类的方法
优点:增加程序灵活性,可拓展性
这里定义了一个多态的统一调用放入全局函数,参数为对象类型的数据,该函数会去调用该对象拥有的多态函数。
# 多态 父类的方法在子类中的不同呈现
class Animal:
#父类Animal
food = 'default'
def eat(self):
print('吃[%s]'%self.food)
return
pass
class Cat(Animal):
def __init__(self):
self.food = 'fish'
def eat(self):
print('吃[%s]'%self.food)
pass
class Wolf(Animal):
def __init__(self):
self.food = 'sheep'
return
def eat(self):
print('吃[%s]' % self.food)
return
pass
def commonInvoke(obj):
'''
统一调用函数,不区分类只要有定义了多态方法即可直接调用多态函数
:param obj: 对象类型数据
:return:
'''
obj.eat()
return
objList = [Animal(),Cat(),Wolf()]
for item in objList:
commonInvoke(item)
pass
cat1 = Cat()
cat1.eat()
wolf1 = Wolf()
wolf1.eat()
鸭子类型(duck typing)
在程序设计中,鸭子类型是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。
“鸭子测试”可以这样表述:”当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。
七、Property属性函数
在类中,定义一个类属性来实现调用该类属性以直接访问私有属性。
可以理解为新建了一个属性,使用property定义并使其可以拥有函数的功能(访问和修改私有属性)。
例如
pro1 = property(getAge,setAge) # 属性pro1可以访问和修改私有age
使用装饰器
@property
# 使用装饰器对实例方法进行装饰,提供一个getter方法
@私有属性.setter
# 使用装饰器,提供一个setter方法
使用property和装饰器效果相同
class Person:
def __init__(self):
self.__age = 23
self.__name = 'lzh'
return
def getAge(self):
return self.__age
def setAge(self,age):
if age < 0:
print('年龄不能小于0')
pass
else:
self.__age = age
pass
return
age = property(getAge,setAge)
@property
def name(self):
return self.__name
@name.setter
def name(self,name):
self.__name = name
pass
p1 = Person()
print(p1.age)
print(p1.name)
p1.name = 'ssd'
print(p1.name)
'''
23
lzh
ssd
'''
八、单例模式
顾名思义就是只能创建一个实例的类
实现方法:
重写__ new__函数,并在其中判断是否有该类的实例存在。若不存在,则创建实例,若存在,返回原来创建好的实例。
class SingleCase(object):
__instance = None # 存放创建的实例对象
__inited = False # True表示__init__已被调用过一次
def __new__(cls, *args, **kwargs):
if not cls.__instance: # 实例对象为空,未创建
cls.__instance = super(SingleCase,cls).__new__(cls)
# 创建实例对象
return cls.__instance
else: # 实例对象非空,已创建
return cls.__instance # 返回原实例对象
def __init__(self):
if not SingleCase.__inited: # SingleCase类未曾被初始化
self.name = 'Lzh'
self.age = 23
SingleCase.__inited = True # 标识__inited为True,表明已被初始化
return
def getObject(self):
return self.__instance
def getInited(self):
return self.__inited
Object = property(getObject)
Init = property(getInited)
pass
single1 = SingleCase()
print(single1.name,single1.Object,single1.Init)
'''
Lzh <__main__.SingleCase object at 0x000001DE68A70D90> True
'''
以上是关于Python面向对象:一篇文章掌握面向对象的基础的主要内容,如果未能解决你的问题,请参考以下文章