Python面向对象编程

面向对象编程

编程范式

编程是程序猿使用数据结构+算法,通过特定的编程语言组成的代码来告诉计算机如何执行任务。条条大路通罗马,每个程序员解决同样的问题代码几乎都不相同,每一种编程任务会有很多条实现方法。对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。两种最重要的编程范式分别是面向过程编程和面向对象编程。

面向过程编程(Procedural Programming)

Procedural programming uses a list of instructions to tell the computer what to do step-by-step.
面向过程编程就是程序从上到下一步步执行,从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。

面向对象编程(OOP——Object Oriented Programming)

OOP编程是利用"类"和"对象"来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更加方便有效率。

类的基础语法

class Policeman:

    def __init__(self):
        print("Start!>>>>>")
        self.name = "Jack"
        self.gender = "male"
        self.skill = "翻跟斗"

p1 = Policeman()

控制台输出结果:
Start!>>>>>

注:

  • 类名要大写
  • __init__函数名称是固定的
  • __init__函数必须传递一个参数self
  • __init__函数是在对象创建时自动执行的

属性的修改和删除

p1 = Policeman()
print(p1.__dict__)
print(p1.__dict__["name"])
print(p1.name)

p1.gender = "不详"
print(p1.gender)

del p1.gender
print(p1.__dict__)

既然__int__作为一个函数,类是一个模板,那么,可以在创建对象时传递类的参数


class Policeman:

    def __init__(self, name, gender, skill):
        print("开始>>>>>>")
        self.name = name
        self.gender = gender
        self.skill = skill
        print(self.__dict__)

    def job(self):
        print("%s抓小偷" % self.name)

Jack = Policeman("Jack", "male", "翻跟斗")
print(Jack.name, Jack.gender, Jack.skill)

Alice = Policeman("Alice", "femal", "跳舞")
Alice.job()

如果类中的函数名称不是__init__,那么需要调用才可以执行,而不会自动执行

Python中创建一个类时,自动开辟一块内存空间,我们之前给类设置属性时,使用__init__方法


class Policeman:

    country = "China"

    def __init__(self, name, gender, skill):

        self.name = name
        self.gender = gender
        self.skill = skill

Jack = Policeman("Jack", "male", "翻跟斗")
print(Policeman.country)
  • country变量是一个静态属性,存储在Policeman类中
  • 当创建一个Jack对象时,将Policeman类的指针保存在Jack中,这样对象和类才可以关联起来

class Policeman:

    country = "China"

    def __init__(self, name, gender, skill, country):

        self.name = name
        self.gender = gender
        self.skill = skill
        self.country = country

Jack = Policeman("Jack", "male", "翻跟斗", "USA")
print(Policeman.country)
print(Jack.country)
  • 修改类中的静态属性时,必须使用类名而不能使用对象名
  • 在init方法中,传递了country参数,使用Jack对象调用country属性时,首先调用自己内存空间中的country,如果init方法中没有传递country参数,就会到类的空间中寻找country

什么时候使用静态变量?

    如果一个变量是所有对象共享的值,那么这个变量就应该被定义为静态变量

练一练:计数,一个类创建了多少个对象,创建一个对象,计数加1


class Policeman:

    country = "China"
    count = 0

    def __init__(self, name, gender, skill, country):

        self.name = name
        self.gender = gender
        self.skill = skill
        self.country = country
        Policeman.count += 1

Jack = Policeman("Jack", "male", "翻跟斗", "USA")
print(Policeman.country)
print(Jack.country)
print(Policeman.count)

Alice = Policeman("Alice", "femal", "跳舞", "Russia")
print(Policeman.count)

面向对象继承

继承(inheritance):是面向对象软件技术中的一个概念。如果一个类A继承自另一个类B,就把这个A称为B的子类别,把B称为A的父类别或者超类。继承可以使子类具有父类的各种属性和方法,而不再需要编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重新某些方法,即覆盖父类别原有属性和方法,使其获得与父类别不同的功能,可以很好地提高代码的复用性、扩展性。

class Person:
     
    def __init__(self, name, gender, skill):
         
        self.name = name 
        self.gender = gender
        self.skill = skill 

class Policeman(Person):
    
    def job(self):
        
        print("%s的工作是抓小偷" % self.name)
        
class Thief(Person):
    
    def job(self):
        
        print("%s的工作是偷东西" % self.name)
        
Jack = Policeman("Jack", "male", "翻跟斗")
Jack.job()

Sam = Policeman("Sam", "male", "翻跟斗")
Sam.job()

多继承

class Yanjian:
    
    def weopon(self):
        
        print("三尖两刃刀 + 哮天犬")
        
class Monkey:
    
    def skill(self):
        
        print("七十二变")
        
class XingZhe(Yanjian, Monkey):
    
    pass 

xz = XingZhe()
xz.weopon()
xz.skill()

子类调用父类方法

class Person:
    
    def __init__(self, name, gender, skill):
        
        self.name = name 
        self.gender = gender 
        self.skill = skill 
    
class Policeman(Person):
    
    def __init__(self, name, gender, skill, country):
        
        super().__init__(name, gender, skill) 
        self.country = country 
    
    def say(self):
        
        print(self.name, self.gender, self.skill, self.country)
        
class Thief(Person):
    
    def __init__(self, name, gender, skill, country):
        
        Person.__init__(self, name, gender, skill) 
        self.country = country 
    
    def say(self):
        
        print(self.name, self.gender, self.skill, self.country)
        
Jack = Policeman("Jack", "male", "翻跟斗", "巨人国")
Jack.say()

Sam = Thief("Sam", "male", "翻墙", "小人国")
Sam.say()

多态

同一个对象的多种形态

class Bird:
    
    def fly(self):
        print("小鸟在天空飞翔")
        
class Plane:
    
    def fly(self):
        print("飞机在天空飞翔")
        
class Rocket:
    
    def fly(self):
        print("火箭飞向太空")
        
def fly(obj):
    
    obj.fly()
    
bird = Bird()
plane = Plane()
rocket = Rocket()

注:Python中虽然支持多态,但是有限的支持多态,也不支持运算符重载

封装

封装是指将功能模块化,比如,我们写一个求和函数就是封装,函数使用者不需要了解函数内部是如何实现求和的,只需要调用我们写好的函数就可以了。把很多数据封装到一个对象中,把固定功能的代码封装到一个代码块,将函数、对象打包成模块,这些都属于封装思想。

class Person:
    
    def __init__(self, name, gender, skill):
        self.__name = name 
        self.__gender = gender 
        self.__skill = skill 
        
    def say(self):
        
        print(self.__name, self.__gender, self.__skill)
        
Jack = Person("Jack", "male", "翻跟斗")
# print(Jack.name, Jack.gender, Jack.skill)

print(Jack._Person__name, Jack._Person__gender, Jack._Person__skill)

Jack.say()
 注:在子类中定义的__XXX不会覆盖父类中定义的__XXX,因为子类中变形成了:_子类名__XXX,而父类中变形成了_父类名__XXX。

面向对象进阶

类的约束

class Payment:
    
    def pay(self, money):
        raise Exception("你必须重写pay方法")
    
    
class QQpay(Payment):
    
    def pay(self, money):
        print("QQ支付%d元" % money)
        
class Wechatpay(Payment):
    
    def pay(self, money):
        print("微信支付%d元" % money)
        
class Alipay(Payment):
    
    pass
    
qq = QQpay()
wx = Wechatpay()
zfb = Alipay()

qq.pay(10)
wx.pay(20)
zfb.pay(30)
from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):
    
    @abstractmethod
    def pay(self, money):
        print("继承我必须得重写")
    
    
class QQpay(Payment):
    
    def pay(self, money):
        print("QQ支付%d元" % money)
        
class Wechatpay(Payment):
    
    def pay(self, money):
        print("微信支付%d元" % money)
        
class Alipay(Payment):
    
    pass
    
qq = QQpay()
wx = Wechatpay()
# zfb = Alipay()

def pay(obj, money):
    obj.pay(money)

pay(qq, 10)
pay(wx, 20)
# pay(zfb, 30)

使用抛出异常方法,更加明确,也更加专业

类方法classmethod

类方法通过**@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量**,不能访问实例变量

class Animal:
    
    __feature = "delicious"
    country = "China"
    
    def __init__(self, name, color):
        
        self.name = name 
        self.color = color 
        
    @classmethod
    def get_feature(cls):
        
        print("所有的动物都很%s,尤其是bat" % cls.name)
        
Animal.get_feature()

静态方法staticmethod

静态方法是类中的函数,通过@staticmethod装饰器实现,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。

import time 

class Time:
    
    def __init__(self, hour, minute, second):
        
        self.hour = hour 
        self.minute = minute
        self.second = second 
        
    @staticmethod 
    def current_time():
        
        print("当前时间戳为:%s" % time.time())

    
Time.current_time()

# t1 = Time(5, 30, 20)
# Time.current_time(t1)

面向对象property属性

遵循了统一访问的原则

import math 

class Circle:
    
    def __init__(self, r):
        
        self.__r = r 
        
    @property 
    def area(self):
        
        return round(self.__r**2 * math.pi, 2)
    
    @area.setter 
    def area(self, r): 
        
        self.__r = r

    @area.deleter
    def area(self):
        
        del self.__r 
        print("我删除了")
    
c1 = Circle(5)
print("c1的面积是: ", c1.area)

c1.area = 6
print("c1的面积是: ", c1.area)

del c1.area 

print("c1的面积是: ", c1.area) 

反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

Python面向对象中的反射:通过字符串的形式操作对象相关的属性。

class Fruit:
    
    def __init__(self, name, color):
        
        self.name = name 
        self.color = color 
        
    def buy(self, price, num):
        
        print(price * num)
        
apple = Fruit("苹果", "红色")

print(hasattr(apple, "name"))
print(hasattr(apple, "buy"))

print(getattr(apple, "name"))

f = getattr(apple, "buy")
f(5, 10)

delattr(apple, "name")
print(hasattr(apple, "name"))
class WebSite:
    
    def register(self):
        print("欢迎注册")
        
    def login(self):
        print("欢迎登陆")
        
    def home(self):
        print("欢迎进入首页")
        
    def about(self):
        print("关于我们")
        
while True:
    
    choose = input("请输入>>>")
    
    if choose == "register":
        page = WebSite()
        page.register()
    
    elif choose == "login":
        page = WebSite()
        page.login()
        
    elif choose == "home":
        page = WebSite()
        page.home()
        
    elif choose == "about":
        page = WebSite()
        page.about()
class WebSite:
    
    def register(self):
        print("欢迎注册")
        
    def login(self):
        print("欢迎登陆")
        
    def home(self):
        print("欢迎进入首页")
        
    def about(self):
        print("关于我们")

page = WebSite()

while True:
    
    choose = input("请输入>>>")
    if hasattr(page, choose):
        f = getattr(page, choose)
        f()
    else:
        print("输入页面没有找到:404")

单例设计模式__new__

设计模式

  • 设计模式是前人工作的总结和提炼,针对某一特定问题的成熟解决方案
  • 提高代码复用性、增强代码可靠性

单例设计模式

  • 让类创建的对象,在内存中只有唯一的一个实例
  • 每一次实例化生成的对象,内存地址是相同的

例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个音乐播放器里可以播放很多音乐,但是一次只能播放一个音乐

__new__方法

  • __new__方法是由object基类提供的内置静态方法
  • 在内存中为对象分配空间
  • 返回对象引用
  • Python解释器获得对象引用后,将引用作为第一个出参数传递给__init__方法
class Player:
    
    def __new__(self, *args, **kwgrgs):
        print("new执行了")
    
    def __init__(self):
        print("init执行了")
        
video1 = Player()
print(video1)

video2 = Player()
print(video2)
class Player:
    
    __instance = None
    
    def __new__(cls, *args, **kwgrgs):
        print("new执行了")
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
        return cls.__instance
    
    def __init__(self):
        print("init执行了")
        
video1 = Player()
print(video1)

video2 = Player()
print(video2)

只执行一次__init__方法

class Player:
    
    __instance = None
    __flag = False
    
    def __new__(cls, *args, **kwgrgs):
        print("new执行了")
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
        return cls.__instance
    
    def __init__(self):
        
        if not Player.__flag:
            
            print("init执行了")
            Player.__flag = True
        
video1 = Player()
print(video1)

video2 = Player()
print(video2)

__str____repr__

调用__str__情况

  • print(obj)
  • str(obj)
  • 用%s占位

调用__repr__情况

  • 如果没有找到__str__,就会调用__repr__

  • 用%r占位

  • repr(obj)

class Animal:
    
    def __init__(self, name, color):
        
        self.name = name 
        self.color = color 
        
    def __str__(self):
        
        ret = self.name + "是" + self.color
        return ret 
        
        
bat = Animal("蝙蝠", "黑色")
print(bat)
print(str(bat) + "口感很好")
print("蝙蝠的特征:%s" % bat)
class Animal:
    
    def __init__(self, name, color):
        
        self.name = name 
        self.color = color 
        
    def __repr__(self):
        
        ret = self.name + "是" + self.color
        return ret 
        
bat = Animal("蝙蝠", "黑色")
print(bat)
print(str(bat) + "口感很好")
print("蝙蝠的特征:%s" % bat)

print(repr(bat))
print("你了解蝙蝠吗? %r" % bat)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值