Python面向对象:一篇文章掌握面向对象的基础

Posted 晚风Adore

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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面向对象:一篇文章掌握面向对象的基础的主要内容,如果未能解决你的问题,请参考以下文章

python基础8之面向对象引子

面向对象基础一

大数据必学Java基础(四十一):面向对象三大特性之一多态(Polymorphism)

学Python基础面向对象看这一篇文章就够了全网首推

Python基础(二十):面向对象基础

Python基础(二十):面向对象基础