Python编程基础(三)

Python编程基础(三)

打卡第三天啦!!!

面向对象基础(上)

面向对象介绍

  1. OOP
  2. 将数据与函数绑定在一起,进行封装
  3. 面向过程和面向对象

类和对象

  1. 类是模板,由类名、属性、方法构成
  2. 对象是根据模板创建的实例
定义类和对象
# 类名用大驼峰命名法
class Person:
    name='潘小雷'
    age=20
    def watch(self):
        print('看韩剧')
        pass
    def run(self):
        print('跑步')
        pass

# 创建对象
rainy_universe=Person()
print(rainy_universe.name)
print(rainy_universe.age)
rainy_universe.watch()
rainy_universe.run()
# 潘小雷
# 20
# 看韩剧
# 跑步

实例方法与属性

  1. 类的内部使用def关键字可以定义一个实例方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数(名字可以不是self,但是这个位置必须被占用)
  2. 属性:类里面定义的变量(类属性
  3. 定义在方法里面使用self引用的属性称之为实例属性
# 类名用大驼峰命名法
class Person:
    def watch(self):
        print('看韩剧')
        pass
    def run(self):
        print('跑步')
        pass
    def __init__(self):
        self.name='潘小雷' # 实例属性
        self.age=20

# 创建对象
rainy_universe=Person()
print(rainy_universe.name)
print(rainy_universe.age)
rainy_universe.watch()
rainy_universe.run()
# 潘小雷
# 20
# 看韩剧
# 跑步

__init__方法

  1. python自带的内置函数,是魔术方法
  2. 是一个初始化的方法,用来定义实例属性和初始化数据的,在创建对象的时候自动调用,不用手动去调用
  3. 利用传参的机制可以让我们定义功能更强大并且方便的类
# 使用__init__方法前
class People:
    def eat(self):
        print('俺在吃饭')
        pass

rainy_universe=People()
rainy_universe.eat()
rainy_universe.name='雨宙'
rainy_universe.age=19
print(rainy_universe.name,rainy_universe.age)

pan=People()
pan.name='潘小雷'
pan.age=20
print(pan.name,pan.age)
# 俺在吃饭
# 雨宙 19
# 潘小雷 20
# 使用__init__方法后
class People:
    def __init__(self):
        self.name='潘小雷'
        self.age=20
        pass
pan=People()
print(pan.name,pan.age)
# 潘小雷 20

rainy_universe=People()
rainy_universe.name='雨宙'
rainy_universe.age=19
print(rainy_universe.name,rainy_universe.age)
# 雨宙 19
# 改进
class People:
    def __init__(self,name,age):
        self.name=name
        self.age=age
        pass
    def eat(self,food):
        print(self.name+'在吃'+food)
        pass
pan=People('潘小雷',20)
print(pan.name,pan.age)
pan.eat('面条')
# 潘小雷 20
# 潘小雷在吃面条

理解self

  1. self和对象指向同一个内存地址,可以认为self就是对象的引用
class Person:
    def eat(self):
        print(self)
        print('self={}'.format(id(self)))
        pass
    pass

pan=Person()
pan.eat()
print('pan={}'.format(id(pan)))
# <__main__.Person object at 0x000002449D31FFA0>
# self=2493718331296
# pan=2493718331296
  1. 所谓的self,可以理解为对象自己。某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可。
  2. self只有在类中定义实例方法的时候才有意义,在调用的时候不必传入相应的参数,而是由解释器自动地去指向
  3. self的名称可以更改,可以定义成其他的名字

魔术方法

  1. __str__方法
class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
        pass
    def __str__(self):
        return '姓名:{} 年龄:{}'.format(self.name,self.age)
    def eat(self):
        print('吃饭')
        pass
    pass

pan=Person('潘小雷',20)
print(pan)
# 姓名:潘小雷 年龄:20
  1. __new__方法(至少有cls参数代表要实例化的类)
    (1)场景:可以控制创建对象的一些属性限定,经常用来做单例模式的时候来使用
    (2)__new__和__init__函数的区别:__new__类的实例化方法必须返回该实例,否则对象就创建不成功;__init__用来做数据属性的初始化工作,也可以认为是实例的构造方法,接收类的实例self并对其进行构造
    (3)__new__函数要早于__init__函数执行
class Person:
    def __init__(self,name,age):
        print('---------------init-------------')
        self.name=name
        self.age=age
        pass
    def __str__(self):
        return '姓名:{} 年龄:{}'.format(self.name,self.age)
    def __new__(cls,*args,**kwargs):
        print('---------------new-------------')
        return object.__new__(cls) #真正创建对象实例
        pass
    def eat(self):
        print('吃饭')
        pass
    pass

pan=Person('潘小雷',20)
print(pan)
# ---------------new-------------
# ---------------init-------------
# 姓名:潘小雷 年龄:20

案例

import time
class Person():
    def __init__(self,name,blood):
        self.name=name
        self.blood=blood
    def __str__(self):
        return '玩家{}血量为{}'.format(self.name,self.blood)
    def attack_methodA(self,enemy):
        print('玩家{} 捅了 玩家{}一刀,玩家{}掉了10滴血'.format(self.name,enemy.name,enemy.name))
        enemy.blood-=10
        pass
    def attack_methodB(self,enemy):
        print('玩家{} 砍了 玩家{}一刀,玩家{}掉了15滴血'.format(self.name, enemy.name, enemy.name))
        enemy.blood-=15
        pass
    def increase_blood(self):
        print('玩家{} 吃药,恢复10滴血'.format(self.name))
        self.blood+=10
        pass

xm=Person('西门吹雪',100)
ygc=Person('叶孤城',100)
while True:
    if(xm.blood<=0 or ygc.blood<=0):
        break
        pass
    xm.attack_methodA(ygc)
    print(xm)
    print(ygc)
    print('-------------------------------')
    ygc.attack_methodB(xm)
    print(xm)
    print(ygc)
    print('-------------------------------')
    xm.increase_blood()
    print(xm)
    print(ygc)
    print('-------------------------------')
    time.sleep(1)
    pass

面向对象基础(中)

析构方法

  1. 当一个对象被删除或者被销毁时,Python解释器也会默认调用一个方法,这个方法为__del__()方法,也称为析构方法
  2. 程序执行结束自动调用析构方法
  3. 当对象被手动销毁时也会自动调用__del__方法
  4. 析构函数一般用于资源回收
class Animal:
    def __init__(self,name):
        self.name=name
        print('这是构造初始化方法')
        pass
    def __del__(self):
        print('这是析构方法')
        pass
cat=Animal('小猫')
# 这是构造初始化方法
# 这是析构方法
class Animal:
    def __init__(self,name):
        self.name=name
        print('这是构造初始化方法')
        pass
    def __del__(self):
        print('这是析构方法')
        pass
cat=Animal('小猫')
del cat # 手动删除对象
input('程序等待中')
# 这是构造初始化方法
# 这是析构方法
# 程序等待中

继承

单继承
  1. 对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一去实现
class Animal:
    def eat(self):
        print('吃')
        pass
    def drink(self):
        print('喝')
        pass

class Dog(Animal):
    def wwj(self):
        print('汪汪叫')
        pass
    pass

class Cat(Animal):
    def mmj(self):
        print('喵喵叫')
        pass
    pass

d1=Dog()
d1.eat()
c1=Cat()
c1.eat()
# 吃
# 吃
多继承
class shenxian:
    def fly(self):
        print('神仙都会飞')
        pass

class Monkey:
    def eat(self):
        print('猴子喜欢吃桃')
        pass

class SunWukong(shenxian,Monkey):
    pass

sunWuKong=SunWukong()
sunWuKong.fly()
sunWuKong.eat()
# 神仙都会飞
# 猴子喜欢吃桃
class D(object):
    def eat(self):
        print('D.eat')
        pass

class C(D):
    def eat(self):
        print('C.eat')
        pass

class B(D):
    pass

class A(B,C):
    pass
a=A()
a.eat()
print(A.__mro__) # 可以显示类的依次继承关系
# 执行顺序:A-》B-》C(-》D)
# C.eat
# (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
重写父类方法

所谓重写,就是子类中,有一个和父亲相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

调用父类方法
class Dog:
    def __init__(self,name,color):
        self.name=name
        self.color=color
        pass

class keji(Dog):
    def __init__(self,name,color,height,weight):
        Dog.__init__(self,name,color) # 调用父类方法
        # super.__init__(name,color) # 另外一种方式 super自动找到父类进而调用方法
        self.height=height
        self.weight=weight
        pass
    def __str__(self):
        return '名字:{} 颜色:{} 高度:{} 重量:{}'.format(self.name,self.color,self.height,self.weight)

kejiA=keji('柯基犬','红色',30,50)
print(kejiA)
# 名字:柯基犬 颜色:红色 高度:30 重量:50

多态

  1. 所谓多态,定义时的类型和运行时的类型不一样,此时就成为多态(同一种行为,对于不同的子类有不同的有不同的行为表现)
  2. 实现多态的前提:
    (1)多态必须发生在父类和子类之间
    (2)子类重写父类的方法
class Person:
    def say_who(self):
        print('我是一个人')
        pass

class Student(Person): # 子类继承父类
    def say_who(self):
        print('我是一个学生') # 子类重写父类方法
        pass

class Teacher(Person):
    def say_who(self):
        print('我是一个老师')
        pass

def commonInvoke(obj):
    obj.say_who()

listObj=[Student(),Teacher()]
for item in listObj:
    commonInvoke(item)
# 我是一个学生
# 我是一个老师

  1. 多态可以增加程序的灵活性,增加程序的扩展性
  2. 鸭子类型:只要看起来像鸭子,就是鸭子

类属性和实例属性

  1. 类属性:就是类对象所拥有的属性,可以被所有类对象的实例对象所共有,类对象和实例对象可以访问
  2. 实例属性:实例对象所拥有的属性,只能通过实例对象访问
  3. 类属性只能通过类对象修改
class Student:
    name='潘小雷' # 属于类属性 就是student类对象所拥有的
    def __init__(self,age):
        self.age=age # 实例属性
        pass
    pass
rainy_universe=Student(19)
print('-----------通过实例对象访问类属性和实例属性------------')
print(rainy_universe.name)
print(rainy_universe.age)
print('-----------通过类对象访问类属性和实例属性--------------')
print(Student.name)
# print(Student.age) # error
# -----------通过实例对象访问类属性和实例属性------------
# 潘小雷
# 19
# -----------通过类对象访问类属性和实例属性--------------
# 潘小雷

class Student:
    name='潘小雷' # 属于类属性 就是student类对象所拥有的
    def __init__(self,age):
        self.age=age # 实例属性
        pass
    pass
Student.name='雨宙' # 类属性只能通过类对象修改
rainy_universe=Student(19)
print('-----------通过实例对象访问类属性和实例属性------------')
print(rainy_universe.name)
print(rainy_universe.age)
print('-----------通过类对象访问类属性和实例属性--------------')
print(Student.name)
# print(Student.age) # error
# -----------通过实例对象访问类属性和实例属性------------
# 雨宙
# 19
# -----------通过类对象访问类属性和实例属性--------------
# 雨宙

类方法和静态方法

  1. 类方法:类对象所拥有的方法,需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,类方法可以通过类对象,实例对象调用
class People:
    country='China'
    # 类方法,用@classmethod进行修饰
    @classmethod
    def get_country(cls):
        return cls.country
        pass
    @classmethod
    def change_country(cls,data):
        cls.country=data
        pass
    pass

# 通过类对象去引用
print(People.get_country()) # China
# 通过实例对象去引用
peopleA=People()
print(peopleA.get_country()) # China
People.change_country('英国')
print(People.get_country()) # 英国
  1. 静态方法:类对象所拥有的方法,需要用@staticmethod来表示静态方法,静态方法不需要任何参数
  2. 一般情况下,不会通过实例对象访问静态方法
  3. 由于静态方法主要存放逻辑性的代码,本身和类以及实例对象没有交互,在静态方法中,不会涉及到类中方法和属性的操作
class People:
    country='China'
    @staticmethod
    def getData():
        return People.country # 通过类对象去引用
    pass

p=People()
print(p.getData()) # China
import time
class TimeTest:
    def __init__(self,hour,min,second):
        self.hour=hour
        self.min=min
        self.second=second
    @staticmethod
    def showTime():
        return time.strftime("%H:%M:%S",time.localtime())
    pass

print(TimeTest.showTime()) # 11:23:26
  1. 类方法第一个参数是类对象,简称cls,进而去引用类对象的属性和方法;实例方法的第一个参数必须是self,通过这个self可以去引用类属性或实例属性,若存在相同名称的实例属性和类属性的话,实例属性的优先级最高;静态方法不需要定义额外的参数,若是要引用属性的话,则可以通过类对象或实例对象去引用

面向对象基础(下)

私有化属性

  1. 两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问
  2. 私有化属性不能在外部直接访问,可以在类的内部随意使用
  3. 子类不能继承父类的私有化属性,只能继承公共的属性和行为
class Person:
    def __init__(self):
        self.__name='潘小雷'
        pass
    def __str__(self):
        return '姓名:{}'.format(self.__name)

class Student(Person):
    pass

pan=Person()
# print(pan.__name) # error 私有属性不能在外部使用
print(pan.__str__()) # 姓名:潘小雷
stu=Student()
# print(stu.__name) # error 私有属性不能被继承
class Person:
    def __init__(self):
        self.__name='潘小雷'
        pass
    def change_name(self,data):
        self.__name=data
        pass
    def __str__(self):
        return '姓名:{}'.format(self.__name)
    pass

pan=Person()
pan.change_name('雨宙')
print(pan.__str__())
# 姓名:雨宙

私有化方法

  1. 私有化方法,在方法名前面加两个下划线
class Animal:
    def eat(self):
        print('吃东西')
        pass
    def __run(self):
        print('飞快地跑')
        pass

class Bird(Animal):
    pass

b1=Bird()
b1.eat() # 吃东西
# b1.__run() # error

Property属性

两种实现方式

class Person:
    def __init__(self,age):
        self.__age=age
        pass
    def get_age(self):
        return self.__age
    def set_age(self,age):
        if age<0:
            print('年龄不能小于0')
            pass
        else:
            self.__age=age
            pass
    age=property(get_age,set_age)
    pass
p1=Person(20)
print(p1.age) # 20
p1.age=19
print(p1.age) # 19
# 通过装饰器实现
class Person:
    def __init__(self,age):
        self.__age=age
        pass

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self,parms):
        if parms<0:
            print('年龄不能小于0')
            pass
        else:
            self.__age=parms
            pass
    pass
p1=Person(20)
print(p1.age) # 20
p1.age=19
print(p1.age) # 19

__new__方法

  1. 作用:创建并返回一个实例对象
class Animal:
    def __init__(self):
        self.color='黄色'
        pass
    # 默认结构
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls,*args,**kwargs)
    pass

cat=Animal()
单例模式
  1. 是一种常用设计模式
  2. 一个类只有一个实例存在
class DatabaseClass(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):# hasattr不能处理私有变量,改成__instance会报错
            cls._instance=super().__new__(cls, *args, **kwargs)
        return cls._instance
    pass

db1=DatabaseClass()
db2=DatabaseClass()
print(id(db1))
print(id(db2))
# 1835757881480
# 1835757881480
# 另一种方法
class DatabaseClass(object):
    __instance=None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance=super().__new__(cls, *args, **kwargs)
        return cls.__instance
    pass

db1=DatabaseClass()
db2=DatabaseClass()
print(id(db1))
print(id(db2))

错误与异常处理

  1. 用一个块可以捕获多个不同类型的异常,使用Exception可以捕获到所有的异常
try:
    print(b)
    pass
except NameError as msg:
    print(msg)
    pass
print('错误处理完毕')
# name 'b' is not defined
# 错误处理完毕
  1. 不需要在每个可能出错的地方去捕获,只要在合适的层次去捕获错误就可以了
def A(s):
    return 10/s
def B(s):
    return A(s)*2
def main():
    try:
        B(0)
        pass
    except Exception as msg:
        print(msg)
        pass
    pass
main()
# division by zero
  1. 异常抛出机制:如果在运行时发生异常,解释器会查找相应的异常捕获类型,如果在当前函数中没有找到的话,会将异常传递给上层调用函数,如果在最外层没有找到的话,解释器会退出程序
  2. 语法格式:
    try:
      可能出现错误的代码块
    except:
      出错之后执行的代码块
    else:
      没有出错的代码块
    finally:
      不管有没有出错都执行的代码块
自定义异常
class ToolongException(Exception):
    def __init__(self,len):
        self.len=len
        pass
    def __str__(self):
        return '输入长度为{}'.format(self.len)+',超过长度'
    pass

def name_test():
    name=input('请输入姓名:')
    try:
        if len(name)>5:
            raise ToolongException(len(name))
        else:
            print(name)
            pass
        pass
    except ToolongException as msg:
        print(msg)
        pass
name_test()
# 请输入姓名:啦啦啦啦啦啦
# 输入长度为6,超过长度

动态绑定数据和方法

  1. 绑定实例属性和方法
import types # 添加方法的库
def dynamicMethod(self):
    print('姓名:{} 年龄:{} 体重:{}'.format(self.name,self.age,self.weight))
class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
        pass
    def __str__(self):
        return '姓名:{} 年龄:{}'.format(self.name,self.age)

pan=Student('潘小雷',20)
pan.weight=68 # 动态绑定属性
pan.printInfo=types.MethodType(dynamicMethod,pan) # 动态绑定方法
pan.printInfo()
# 姓名:潘小雷 年龄:20 体重:68
  1. 绑定类属性和方法
@classmethod
def classTest(cls):
    print('这是一个绑定类方法')
    pass
class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
        pass
    def __str__(self):
        return '姓名:{} 年龄:{}'.format(self.name,self.age)
Student.weight=80
Student.testMethod=classTest
Student.testMethod()

__slots__属性

  1. 限制要添加的实例属性
  2. 子类未声明__slots__属性时,不会继承父类的__slots__属性,此时子类是可以随意属性赋值
class Student(object):
    __slots__ = ('name','age')
    def __str__(self):
        return '姓名:{} 年龄:{}'.format(self.name,self.age)
    pass

whale=Student()
whale.name='鲸鱼'
whale.age=20
# whale.score=100 # error
# print(whale.__dict__) # 所有的属性都存储在这里,定义slots变量后不能随意创建不在其中的属性
print(whale)
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值