面向对象
对于面向对象的学习,我整理了网上的一些资料,希望可以帮助到各位!!!
“一切皆为对象”
python中的面向对象的学习主要是类和对象。
在面向对象编程的世界里,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为对象,对象可以接收消息,解决问题的方法就是创建对象并向对象发出各种各样的消息;通过消息传递,程序中的多个对象可以协同工作,这样就能构造出复杂的系统并解决现实中的问题。
类的定义
语法:
class Dog():
# 类属性
name = "局长"
sex = "公"
def __init__(self, name=None):
if name:
self.name = name
# 类方法
def eat(self):
print(self.name, "吃肉!")
def say(self):
print("我是吼的方法")
# 使用示例
dog1 = Dog()
dog2 = Dog("旺财")
dog1.eat()
dog2.eat()
类中的方法和变量的定义
类中的方法和变量是为了描述事物的行为和特征
类中定义的方法被称为:成员方法
类中定义的变量被称为成员变量,也被称为属性 [os.name]
成员变量:类具有的特征
成员方法:类具有的行为
类存在的意义:拥有相同特征和行为的对像可以抽取出来一个类,类的存在是为了创建一个具体
的对象
类中方法和属性的使用
创建对象【实例化对象】
已知类,通过类创建对象对象的创建过程被对象的实例化过程
class Dog():
# 类属性
name = "局长"
sex = "公"
# 类方法
def eat(self):
print(Dog.name, "吃肉!")
def say(self):
print("我是吼的方法")
# 通过Dog类创建对象
labuladuo = Dog()
# 通过对象访问方法
labuladuo.eat()
labuladuo.say()
# 通过对象访问属性
print(labuladuo.name)
print(labuladuo.sex)
构造函数
class GirlFriend:
# 构造函数参数是对象相关的属性
def __init__(self, name, age):
# 对象属性
self.name = name
self.age = age
print("构造函数的触发时机是:当创建对象的时候自动")
# 对象方法
def say(self):
print(self.name, "原神,启动!!!")
def sing(self):
print("第五人格,启动!!!")
# 当创建对象的时候,会自动调用__init__()
n = GirlFriend("py小王子", 21)
n.say()
析构函数
class GirlFriend:
# 对象方法
def sing(self):
print("可是困住我青春的人,始终没有回头看我一眼。")
# 析构函数:触发时机是当对象被删除时,会被自动调用,释放内存
def __del__(self):
print("脚本运行结束,释放内存")
# 当创建对象的时候,会自动调用__init__()
n = GirlFriend()
n.sing()
print("我是最后执行的一句代码了!")
# 可以添加下面这行代码来手动触发析构函数(不过在脚本正常结束时也会自动触发)
# del n
封装
class Girl:
def __init__(self, name, sex, height):
self.name = name
self.sex = sex
self.height = height
# 比如我的青春停留年龄,在外面不能轻易的访问,需要把年龄设置为私有属性__
self.__age = 18
def say(self):
print("哥哥,我坐你旁边,姐姐不会生气吧!")
# 在类的内部可以访问私有属性
def sayAge(self, boyFriend):
if boyFriend == "py小王子":
print(f"{self.name}偷偷的告诉{boyFriend}说:你的朋友太多了,这显示的我不是很重要了")
else:
print("年少之忆,也可叹,只是当时已惘然呐")
# 私有方法
# 接吻
def __kiss(self):
print("一吻定终身!")
# 类中可以访问私有方法
def love(self, relationship):
if relationship == "情侣关系":
self.__kiss()
else:
print("离开")
is_girl = Girl("她", "美女", 165)
print(is_girl.name)
print(is_girl.sex)
print(is_girl.height)
# print(is_girl.age) # 将age设置为私有属性后,外部不能直接访问
is_girl.say()
is_girl.sayAge("py小王子")
is_girl.love("未知关系")
get函数和set函数
get函数和set函数并不是系统的函数,而是自定义的,为了和封装的概念相吻合,起名为getXxx
和setXxx
- get函数:获取值
- set函数:赋值【传值】
# 第一种访问和设置私有属性的方式 get和set函数
class Girl:
def __init__(self, name, age):
self.name = name
self.__age = age
# 访问私有属性
# 命名规则:get+私有属性名(属性名单词首字母大写)
def getAge(self):
return self.__age
# 设置私有属性
# 命名规则:set+私有属性名(属性名单词首字母大写)
def setAge(self, age):
self.__age = age
zhi = Girl("她", 21)
print(zhi.name)
# 不能直接访问私有属性,以下代码是错误的:
# print(zhi.__age)#AttributeError: 'Girl' object has no attribute '__age'
# 访问私有属性
age = zhi.getAge()
print(age) # 21
# 设置私有属性
zhi.setAge(18)
print(zhi.getAge()) # 18
@property装饰器
# 第一种访问和设置私有属性的方式 get和set函数
class Girl:
def __init__(self, name, age):
self.name = name
self.__age = age
# 访问私有属性
# 命名规则:get+私有属性名(属性名单词首字母大写)
def getAge(self):
return self.__age
# 设置私有属性
# 命名规则:set+私有属性名(属性名单词首字母大写)
def setAge(self, age):
self.__age = age
# 通过装饰器@property获取私有属性age
# 相当于getAge()
@property
def age(self):
return self.__age
# 通过装饰器设置私有属性
@age.setter
def age(self, new_age):
self.__age = new_age
zhi = Girl("她", 21)
print(zhi.getAge()) # 21
zhi.setAge(18)
print(zhi.getAge()) # 18
print()
print(zhi.age) # 18 通过装饰器访问私有属性,访问格式:对象名.私有属性名
zhi.age = 19 # 通过装饰器设置私有属性,格式:对象名.私有属性名=值
print(zhi.age) # 19
动态属性
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student('py小王子', 21)
# 为Student对象动态添加sex属性
stu.sex = '男'
print(stu.__dict__)
class Student:
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student('py小王子', 21)
# AttributeError: 'Student' object has no attribute 'sex'
stu.sex = '男'
print(stu.__dict__)
类方法和静态方法
class Animal():
# 类属性
name = "牧羊犬"
# 对象属性
def __init__(self, name, sex):
self.name = name
self.sex = sex
@classmethod
def run(cls):
print("我是类方法")
print(cls.name)
print(cls == Animal) # cls表示的是当前类
"""
静态方法:
1.通过@staticmethod装饰器修饰的方法就是静态方法
2.通过类名或者对象名都可以调用静态方法(推荐使用类名调用)
3.静态方法形式参数中没有cls,在静态方法中不建议调用(类属性\类方法静态方法)
4.静态方法一般是一个单独的方法,只是写在类中
"""
# 静态方法
@staticmethod
def eat():
print("我是静态方法")
# 创建对象
dog = Animal('中华土狗', '公')
# dog.run() # 对象也可以调用类方法,但一般推荐用类名调用类方法
Animal.run() # 类名调用类方法
Animal.eat() # 类名调用静态方法
类中的常用属性
class Animal(object):
def __init__(self, name, sex):
self.name = name
self.sex = sex
def eat(self):
print("吃")
animal = Animal("二哈", "公狗")
# __name__—通过类名访问获取当前类的类名,不能通过对象访问
print(Animal.__name__) # Animal
print()
# __dict__—以字典的形式返回类的属性和方法以及对象的属性
print(Animal.__dict__) # 以字典的形式显示类的属性和方法
print()
print(animal.__dict__) # 以字典的形式显示对象的属性{'name': '二哈', 'sex': '公狗'}
print()
# __bases__ 获取指定类的父类返回的是一个元组
print(Animal.__bases__) # (<class 'object'>,)
print()
# 魔术方法:__str__()和__repr__
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def swim(self):
print("游泳的方法")
# __str__()触发时机:当打印对象的时候,自动触发。一般用它来以字符串的形式返回对象的相关信息,必须使用return返回数据
def __str__(self):
return f"姓名是:{self.name}, 年龄是:{self.age}"
# __repr__()作用和__str__()类似,若两者都存在,执行__str__()
def __repr__(self):
return f"姓名是:{self.name}, 年龄是:{self.age}"
zhi = Person("她", 18)
print(zhi)
继承
概念
如果两个或者两个以上的类具有相同的属性或者成员方法,我们可以抽取一个类出来,在抽取的
类中声明公共的部分
父类的属性和方法子类可以直接使用。
注意:
单继承
简单来说,一个子类只能有一个父类,被称为单继承
语法:
父类:class 父类类名 (object):
子类:
class 子类类名 (父类类名):
说明:一般情况下,如果一个类没有显式的指明父类,则统统书写为object
# 最简单的继承
# 父类
class Person(object):
def say(self):
print("说话的方法")
# 子类
class Boy(Person): # 定义一个子类,将父类的类名传进去子类就继承了父类
def eat(self):
print("子类自己的吃饭的方法")
boy = Boy()
boy.eat() # 子类调用自己的方法
boy.say() # 子类调用父类的方法
# 有构造函数的单继承
# 父类
class Animal(object):
def __init__(self, name, sex):
self.name = name
self.sex = sex
def eat(self):
print("所有的动物都有捕食的技能")
# 子类
class cat(Animal):
def __init__(self, name, sex, tail): # 先继承父类的属性,再重构
# 1.经典的写法
# Animal.__init__(self, name, sex) # 继承父类的构造方法
# 2.隐式的继承父类的构造函数
super().__init__(name, sex)
self.tail = tail # 定义子类自己的属性
def catchMouse(self):
print("猫抓老鼠")
cat_obj = cat("波斯猫", "母", "长尾巴")
print(cat_obj.name)
print(cat_obj.sex)
print(cat_obj.tail)
cat_obj.eat()
cat_obj.catchMouse()
多继承
一个子类可以有多个父类
语法:
# 父亲类
class Father(object):
def __init__(self, surname):
self.surname = surname
def make_money(self):
print("钱难挣!")
# 母亲类
class Mother(object):
def __init__(self, height):
self.height = height
def eat(self):
print("一言不合,就干饭!")
# 子类
class Son(Father, Mother): # 子类继承多个父类时,在括号内写多个父类名称即可
def __init__(self, surname, height, weight):
# 继承父类的构造函数
Father.__init__(self, surname)
Mother.__init__(self, height)
self.weight = weight
def play(self):
print("就这么厉害!")
son = Son("黄", 178, 160)
print(son.surname)
print(son.height)
print(son.weight)
son.make_money()
son.eat()
son.play()
多态
一种事物的多种体现形式,函数的重写其实就是多态的一种体现
在Python中,多态指的是父类的引用指向子类的对象
# 多态:在继承的基础上,(多个子类继承一个父类,并且重写父类的一个方法),去调用子类的方法可以实现不同的功能。
# 父类
class Animal():
def eat(self):
print("吃的方法")
# 子类
class Fish(Animal):
def eat(self):
print("大鱼吃小鱼,小鱼吃虾米")
class Dog(Animal):
def eat(self):
print("狼行千里吃肉,狗走万里吃粑粑!")
class Cat(Animal):
def eat(self):
print("猫爱吃鱼!")
# 严格意义的多态:使用对象调用eat方法
class Person():
def feed(self, animal):
animal.eat()
fish = Fish()
dog = Dog()
cat = Cat()
# 最简单的多态的体现
fish.eat()
dog.eat()
cat.eat()
# 严格意义的多态的体现
person = Person()
person.feed(dog)
person.feed(cat)
单例设计模式
1.概念
什么是设计模式
什么是单例设计模式
应用场景
模块
Python的模块就是天然的单例设计模式
模块的工作原理:
使用new
class Person(object):
# __init__对象初始化属性时,自动触发
def __init__(self, name):
print("__init__")
self.name = name
# 定义一个类属性,接收创建好的对象
instance = None
@classmethod
def __new__(cls, *args, **kwargs):
print("__new__")
# 如果类属性的instance=None表示该类未创建过对象
if cls.instance == None:
cls.instance = super().__new__(cls)
return cls.instance
p = Person("陈梦")
p1 = Person("陈梦")
p2 = Person("陈梦")
print(p == p1 == p2)
经典案例
import time
# 定义数字时钟类
class Clock(object):
"""数字时钟"""
def __init__(self, hour=0, minute=0, second=0):
"""初始化方法
:param hour: 时
:param minute: 分
:param second: 秒
"""
self.hour = hour
self.min = minute
self.sec = second
def run(self):
"""走字"""
self.sec += 1
if self.sec == 60:
self.sec = 0
self.min += 1
if self.min == 60:
self.min = 0
self.hour += 1
if self.hour == 24:
self.hour = 0
def show(self):
"""显示时间"""
return f'{self.hour:0>2d}:{self.min:0>2d}:{self.sec:0>2d}'
# 创建时钟对象
clock = Clock(00, 00, 00)
while True:
# 给时钟对象发消息读取时间
print(clock.show())
# 休眠1秒钟
time.sleep(1)
# 给时钟对象发消息使其走字
clock.run()
class Point(object):
"""屏面上的点"""
def __init__(self, x=0, y=0):
"""初始化方法
:param x: 横坐标
:param y: 纵坐标
"""
self.x, self.y = x, y
def distance_to(self, other):
"""计算与另一个点的距离
:param other: 另一个点
"""
dx = self.x - other.x
dy = self.y - other.y
return (dx * dx + dy * dy) ** 0.5
def __str__(self):
return f'({self.x}, {self.y})'
p1 = Point(3, 5)
p2 = Point(6, 9)
print(p1, p2)
print(p1.distance_to(p2))
总结
“路漫漫其修远兮,吾将上下而求索”
恭喜你学会了面向对象,快去试试吧!!!