欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > Python面向对象

Python面向对象

2024/10/24 5:17:41 来源:https://blog.csdn.net/2401_86120676/article/details/140802390  浏览:    关键词:Python面向对象

一切皆对象,将现实世界事务使用类与实例来模拟(e.g. 灯、汽车、导弹、杯子)

一、三大特性

1.封装:

数据:(e.g. 名字、年纪);数据相关操作:(e.g. 获取名字、设置名字、获取年纪、设置年纪)

class Students:def __init__(self, name, age):print("初始化函数")self.name = nameself.age = agedef get_self(self):return selfdef describe_self(self):return self.ages0 = Students("x", 417)
print(id(s0), isinstance(s0, Students))
print(s0.name, s0.age)
s1 = s0.get_self()
print(s1 == s0.get_self(), s1 is s0.get_self())
print(id(s1), id(s0.get_self()))
print(s1)
s2 = s0.get_self()
print(s1 == s2, s1 is s2)

 

2.继承:

子类拥有父类的数据以及操作,子类不需要从新编写。

子类(派生类),父类(基类)。

__base__:获取父类; __bases__:获取父类元组; __class__:返回实例对应的类。

# 子类拥有父类的数据以及操作
# 子类  派生类
# 父类  基类
"""
object是所有类的父类
Python3中可以省略父类objectobject 是基类,父类
Person 是object的子类   是SuperPerson的父类
SuperPerson 是Person的子类子类拥有父类的功能方法,先在子类中找对应的方法 子类如果没有 则去父类中找  父类也没有则去父类的父类 直到object
"""
import math
class Point(object):def __init__(self, x, y):self.x = xself.y = ydef __str__(self):return f"{self.x} {self.y}"p0 = Point(0, 0)
print(p0)class Circle(Point):def __init__(self, x, y, r):super().__init__(x, y)self.r = rdef __str__(self):return f"{super().__str__()} r:{self.r}"def acreage(self):return math.pi * self.r ** 2c0 = Circle(0, 0, 6)
print(c0)
print(c0.acreage())class Rectangle(Point):def __init__(self, x, y, w, h):super().__init__(x, y)self.w = wself.h = hdef __str__(self):return f"{super().__str__()} w:{self.w} h:{self.h}"def acreage1(self):return self.w * self.hr0 = Rectangle(0, 0, 2, 3)
print(r0)
print(r0.acreage1())

 

        多继承:继承多个父类,java,c# 只支持单继承,通过接口等来实现多继承的功能,Python直接就可以有多个父类。

# 继承多个父类
# java,c# 只支持单继承,通过接口实现多继承功能
# paython直接就可以多个父类
class MoveAble:def __init__(self, speed):self.speed = speeddef move(self):print(f"{self.speed}")def __str__(self):return f"攻速"class SpeakAble:def __init__(self, language):self.language = languagedef speak(self):print(f"{self.language}")def __str__(self):return f"语种"class AttackAble:def __init__(self, skill):self.skill = skilldef attack(self):print(f"使用{self.skill}进攻")def __str__(self):return f"攻击"class Person(MoveAble, SpeakAble):def __init__(self, name, speed, language):# 通过类名表明需要初始化哪个父类 必须传入selfMoveAble.__init__(self, speed)SpeakAble.__init__(self, language)self.name = namedef show(self):print(f"{self.name} 听召 前来")def __str__(self):return f"角色"p0 = Person("x", 230, "chinese")
p0.move()
p0.speak()
p0.show()class YS(Person, AttackAble):def __init__(self, name, speed, language, skill):Person.__init__(self, name, speed, language)AttackAble.__init__(self, skill)def __str__(self):return f"游戏"ys0 = YS("x", 230, "chinese", "平A")
ys0.show()
ys0.move()
ys0.speak()
ys0.attack()print(ys0)# 多继承 mro: method(方法) retrieval(检索) order(顺序)
# python3 使用广度优先
print(YS.mro())

3.多态:

Python中没有多态,也可以理解到处都是多态。

两种形式:
(1).函数同名不同参数,通过*args实现。
(2).父子类多态,函数名参数都相同,但是实现不同,拥有多种实现

# 同名不同参数def my_fun1(a):print(a)my_fun1(6)# 解释器 使用第二个函数 覆盖第一个 (第一个函数丢失)
def my_fun2(a, b):print(a, b)my_fun2(10, 20)# 通过形参*ages实现多态功能
def my_fun(*ages):print(ages)my_fun(1)
my_fun(1, 2, 3)class Animal:def walk(self, speed):print(f"z", speed)class Dog(Animal):def walk(self, speed):print("ywb", speed)class Cat(Animal):def walk(self, speed):print("zlzq", speed)

 

二、类与实例

类:是对现实世界描述的一种类型;”class 类名: pass“,类名是大驼峰;是抽象的,约定了未来实例应该有的内容,是实例的模板。

实例:调用类则生成实例,类名() 产生实例;实例是具体的,有具体数据,实例的内容依赖于类。

1.类中内容、self

self:出现在类内来代表未来的实例,需要通过实例来访问。

初始化函数:__init__(self);通过初始化self来初始化未来的实例;向self中添加数据 就是向实例中添加数据。

(1).实例属性
向实例中添加的数据;类内:通过self;类外:通过实例;需要通过实例来访问。
class MyClass3:def __init__(self, name):self.name = namem1 = MyClass3(6)
print(m1.name)
(2).实例方法

第一个形参是self;类内:通过self;类外:通过实例;需要通过实例来访问。

class MyClass4:def __init__(self, x):self.x = xdef instance_method(self, y):return self.x + ym0 = MyClass4(6)
result = m0.instance_method(2)
print(result)
(3).类属性

向类中添加数据,获取与设置直接通过类名。
注意事项:通过实例可以获取类属性(不推荐);通过实例不可以设置类属性

class MyClass2:class_attribute = 10print(MyClass1.class_attribute)
(4).类方法

第一个形参一般是cls;带有装饰器classmethod,将第一个形参编程类名。

目的:为了获取类相关信息(类名、父类、类注释)

实例可以获取类方法(不推荐)

class MyClass1:class_attribute = 10@classmethoddef class_method(cls, multiplier):return cls.class_attribute * multiplierresult = MyClass1.class_method(6)
print(result)
(5).静态方法

        没有特殊形参,有装饰器staticmethod将方法升级为静态方法,通过类名调用,实例可以访问(不推荐),项目的辅助类一般都会使用静态方法。

class MyClass:@staticmethoddef static_method(x, y):return x + yresult = MyClass.static_method(2, 6)
print(result)

2.抽象类

        一个特殊的类:内部可以编写抽象方法,抽象类不能直接实例化,也可以编写普通实例方法。子类继承抽象类,必须实现抽象类的抽象方法。

"""
抽象类:不直接实例化 通过子类来产生实例
"""
from abc import ABC, abstractmethodclass Animal(ABC):"""抽象类:拥有抽象方法 不能直接实例化通过装饰器 abstractmethod把walk变为抽象方法"""@abstractmethoddef walk(self):passdef eat(self):print("c")# a0 = Animal()
# print(a0, isinstance(a0, Animal))class Dog(Animal):"""抽象类子类: 必须实现抽象类中的抽象方法"""def walk(self):print("ywb")dog = Dog()
dog.eat()
dog.walk()
print(isinstance(dog, Dog), isinstance(dog, Animal))class Cat(Animal):def walk(self):print("sxt")cat = Cat()
cat.eat()
print(isinstance(cat, Cat), isinstance(cat, Animal))

 

3.单例类

只有一个实例

        通过控制构造函数判定是否需要从新生成实例:第一次,生成,放入类属性;以后,返回第一次生成的实例。

class Manage(object):instance = Nonedef __new__(cls, *args, **kwargs):"""对构造函数进行控制 不是每次都生成新的实例1、对类属性instance判断 如果不为空 则直接把他返回2、对类属性instance判断 如果为空 就构造一个实例 并且把实例赋予instance:param args::param kwargs:"""if not Manage.instance:Manage.instance = super().__new__(cls)return Manage.instancedef __init__(self):"""初始化函数 初始化实例 向self中添加内容"""print("初始化函数执行")m1 = Manage()
m2 = Manage()
print(m1 is m2, m1 is None, m2 is None)class Manage:def __new__(cls, *args, **kwargs):if not hasattr(Manage, "instance"):obj = super().__new__(cls)setattr(Manage, "instance", obj)return getattr(Manage, "instance")m3 = Manage()
m4 = Manage()
print(m3 is m4)

 

三、构造函数与析构函数

1.构造函数:

用于创建实例( self ),返回实例,通过父类来创建实例【super().__new__()】。

2.析构函数:实例不在使用,销毁之前执行。
"""
构造函数:创建并且返回实例(self)
初始化函数:self已经创建完成,可以向self中添加数据析构函数:销毁实例 清理实例内存 实例不再使用则回收实例内存之前会执行对应的析构函数"""class MyClass:def __new__(cls, *args, **kwargs):# 调用父类的new方法创建一个实例instance = super().__new__(cls)print(f"构造函数", id(instance))# 将创建好的实例返回 返回给初始化函数return instancedef __init__(self, name):print(f"初始化函数", id(self))self.name = namemc0 = MyClass("xk")
print(id(mc0), mc0 is None)class MyOpen:def __init__(self, filename, mode="r", encoding="utf8"):self.f = open(filename, mode=mode, encoding=encoding)def read_all(self):return self.f.read()def __del__(self):self.f.close()m0 = MyOpen("./53.魔法函数.py")
print(m0.read_all())

 

四、属性封装与操作

口头称呼:类封装数据与操作,属性与行为;类属性,实例属性,公有属性,私有属性,保护属性。

property:fget,获取触发,@property;fset:设置触发,@属性名.setter;装饰器。

1. 属性封装:

class Person:def __init__(self, name, age, sex, height):self.__name = nameself.age = ageself.__sex = sexself.__height = height# 将指数变为函数@propertydef height(self):return self.__height# 指明属性的setter@height.setterdef height(self, height):self.__height = heightdef get_name(self):return self.__namedef set_name(self, name):if 1 <= len(name) <= 4:self.__name = nameelse:print("bhf")def __get_sex(self):print("发现你在获取")"""当获取属性时 会触发"""return self.__sexdef __set_sex(self, sex):print("发现你在获取")"""当获取属性时 会触发"""if sex in ["男", "女"]:self.__sex = sexelse:print("输入不合法")sex = property(__get_sex, __set_sex)# 封装真正属性 拥有get与set方法
p0 = Person("x", 2000, "n", 190)# 获取设置age 直接使用 (容易产生不合法数据)
print(p0.age)
p0.age = -6
print(p0.age)# 获取设置name 需要通过函数 可以保证数据安全
print(p0.get_name())
p0.set_name("k")
print(p0.get_name())print(p0.sex)
p0.sex = "nan"
print(p0.sex)print(p0.height)
p0.height = 185
print(p0.height)

 

 2.属性操作:

"""
todo  属性 attribute
delattr: delattr(对象,"属性名") 返回布尔值
getattr: getattr(对象,"属性名") 返回属性值
hasattr: hasattr(对象,"属性名") 返回布尔值
setattr: setattr(对象,"属性名",属性值)
"""import typesclass Person:passp = Person()
p.name = "x"
Person.MAX_AGE = 2000print(hasattr(p, "name"), hasattr(p, "MAX_AGE"))
print(hasattr(Person, "MAX_AGE"))p.get_name = types.MethodType(lambda self: self.name, p)@classmethod
def info(cls):return cls.__name__Person.info = info@staticmethod
def my_max(a, b):return a if a > b else bPerson.my_max = my_maxprint(hasattr(p, "get_name"), hasattr(p, "info"), hasattr(Person, "info"), hasattr(Person, "my_max"))if hasattr(p, "get_name"):value = getattr(p, "get_name")print(f"属性值为:{value()}")if hasattr(p, "age"):pass
else:print("未发现属性age")setattr(p, "age", 2000)if hasattr(p, "age"):print("设置成功后的age值为", getattr(p, "age"))delattr(p, "age")if not hasattr(p, "age"):print("删除成功")

 

五、Python是一门解释性语言

可以向类中动态添加内容。

添加实例属性:实例名.属性名=值;

添加实例方法:实例名.实例方法=types.MethodType(原始方法名, 实例),原始方法第一个参数是self;

添加类属性:向类中添加类属性 类可以正常访问 所有实例均可访问。

添加类方法:向类中添加类方法  方法格式符合类方法格式  类与所有实例均可访问。

添加静态方法:向类中添加静态方法  方法要符合静态方法格式  类与实例均可访问。

import typesclass Person:passp0 = Person()
p = Person()
# 向实例中添加实例数据  其他实例无影响
p.name = "张飞"
print(p.name)def my_set_name(self, name):self.name = name# 向实例中添加实例数据 其他实例无影响
p.set_name = types.MethodType(my_set_name, p)p.set_name("赵云")
print(p.name)# 向类中添加类属性 类可以正常访问 所有实例均可访问
Person.MAX_AGE = 120
print(Person.MAX_AGE, p.MAX_AGE, p0.MAX_AGE)@classmethod
def my_info(cls):print(cls.__bases__)# 向类中添加类方法  方法格式符合类方法格式  类与所有实例均可访问
Person.info = my_infoPerson.info()
p0.info()
p.info()#
@staticmethod
def my_max(x, y):return x if x > y else y#  向类中添加静态方法  方法要符合静态方法格式  类与实例均可访问
Person.max = my_maxprint(Person.max(10, 20), p.max(50, 100), p0.max(200, 500))

 

六、数据的访问级别

1.公有类型:public,普通名字,类内和类外,子类都可以使用。

2.私有类型:private,以 _ _开头,只能在类内访问。

3.保护类型:protect,以 _ 开头,在类内可以访问,在子类可以访问,在类外、可以 强制访问。

"""
公有类型:public 普通名字 类内与类外、子类都可以使用
私有类型:private 以__开头 只能在类内访问
保护类型:protect 以_开头 在类内可以访问 在子类可以访问 在类外可以强制访问"""class MyClass:def __init__(self, name, __age, _sex):self.name = nameself.__age = __ageself._sex = _sexdef get_age(self):return self.__agedef set_age(self, __age):self.__age = __agedef get_sex(self):return self._sexdef set_sex(self, _sex):self._sex = _sexdef get_name(self):return self.namedef set_name(self, name):self.name = namedef __str__(self):return f"name:{self.name} age:{self.__age} sex:{self._sex}"m0 = MyClass("x", 2000, "n")
print(m0)
m0.set_name("kk")
print(m0.get_name())
m0.set_age(10000)
print(m0.get_age())
m0.set_sex("n")
print(m0.get_sex())
m0.set_name("sz")
print(m0.get_name())
m0.set_sex("nv")
print(m0.get_sex())
m0.set_age(1000)
print(m0.get_age())

        Python 中的面向对象编程为程序员提供了一种结构化的方法来组织和管理代码,通过类和对象可以更好地模拟现实世界的复杂性,并提供了更灵活和可扩展的代码结构。 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com