概述
Python编程基础(三)
打卡第三天啦!!!
面向对象基础(上)
面向对象介绍
- OOP
- 将数据与函数绑定在一起,进行封装
- 面向过程和面向对象
类和对象
- 类是模板,由类名、属性、方法构成
- 对象是根据模板创建的实例
定义类和对象
# 类名用大驼峰命名法
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
# 看韩剧
# 跑步
实例方法与属性
- 在类的内部,使用def关键字可以定义一个实例方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数(名字可以不是self,但是这个位置必须被占用)
- 属性:类里面定义的变量(类属性)
- 定义在方法里面使用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__方法
- python自带的内置函数,是魔术方法
- 是一个初始化的方法,用来定义实例属性和初始化数据的,在创建对象的时候自动调用,不用手动去调用
- 利用传参的机制可以让我们定义功能更强大并且方便的类
# 使用__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
- 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
- 所谓的self,可以理解为对象自己。某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可。
- self只有在类中定义实例方法的时候才有意义,在调用的时候不必传入相应的参数,而是由解释器自动地去指向
- self的名称可以更改,可以定义成其他的名字
魔术方法
- __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
- __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
面向对象基础(中)
析构方法
- 当一个对象被删除或者被销毁时,Python解释器也会默认调用一个方法,这个方法为__del__()方法,也称为析构方法
- 程序执行结束自动调用析构方法
- 当对象被手动销毁时也会自动调用__del__方法
- 析构函数一般用于资源回收
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('程序等待中')
# 这是构造初始化方法
# 这是析构方法
# 程序等待中
继承
单继承
- 对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一去实现
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)子类重写父类的方法
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)
# 我是一个学生
# 我是一个老师
- 多态可以增加程序的灵活性,增加程序的扩展性
- 鸭子类型:只要看起来像鸭子,就是鸭子
类属性和实例属性
- 类属性:就是类对象所拥有的属性,可以被所有类对象的实例对象所共有,类对象和实例对象可以访问
- 实例属性:实例对象所拥有的属性,只能通过实例对象访问
- 类属性只能通过类对象修改
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
# -----------通过类对象访问类属性和实例属性--------------
# 雨宙
类方法和静态方法
- 类方法:类对象所拥有的方法,需要用装饰器@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()) # 英国
- 静态方法:类对象所拥有的方法,需要用@staticmethod来表示静态方法,静态方法不需要任何参数
- 一般情况下,不会通过实例对象访问静态方法
- 由于静态方法主要存放逻辑性的代码,本身和类以及实例对象没有交互,在静态方法中,不会涉及到类中方法和属性的操作
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
- 类方法第一个参数是类对象,简称cls,进而去引用类对象的属性和方法;实例方法的第一个参数必须是self,通过这个self可以去引用类属性或实例属性,若存在相同名称的实例属性和类属性的话,实例属性的优先级最高;静态方法不需要定义额外的参数,若是要引用属性的话,则可以通过类对象或实例对象去引用
面向对象基础(下)
私有化属性
- 两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问
- 私有化属性不能在外部直接访问,可以在类的内部随意使用
- 子类不能继承父类的私有化属性,只能继承公共的属性和行为
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__())
# 姓名:雨宙
私有化方法
- 私有化方法,在方法名前面加两个下划线
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__方法
- 作用:创建并返回一个实例对象
class Animal:
def __init__(self):
self.color='黄色'
pass
# 默认结构
def __new__(cls, *args, **kwargs):
return super().__new__(cls,*args,**kwargs)
pass
cat=Animal()
单例模式
- 是一种常用设计模式
- 一个类只有一个实例存在
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))
错误与异常处理
- 用一个块可以捕获多个不同类型的异常,使用Exception可以捕获到所有的异常
try:
print(b)
pass
except NameError as msg:
print(msg)
pass
print('错误处理完毕')
# name 'b' is not defined
# 错误处理完毕
- 不需要在每个可能出错的地方去捕获,只要在合适的层次去捕获错误就可以了
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
- 异常抛出机制:如果在运行时发生异常,解释器会查找相应的异常捕获类型,如果在当前函数中没有找到的话,会将异常传递给上层调用函数,如果在最外层没有找到的话,解释器会退出程序
- 语法格式:
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,超过长度
动态绑定数据和方法
- 绑定实例属性和方法
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
- 绑定类属性和方法
@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__属性
- 限制要添加的实例属性
- 子类未声明__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)
最后
以上就是专注方盒为你收集整理的Python编程基础(三)Python编程基础(三)的全部内容,希望文章能够帮你解决Python编程基础(三)Python编程基础(三)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复