Solowang 发表于 2024-7-15 10:47

python 面向对象

本帖最后由 Solowang 于 2024-7-15 11:12 编辑

我是个新手在学习的道路上发现基础没有打好   没办法那就补充基础知识 一、类方法和静态方法定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);调用:实例对象和类对象都可以调用。原则上,类方法是将类本身作为对象进行操作的方法。假设有个方法,且这个方法在逻辑上采用类本身作为对象来调用更合理,那么这个方法就可以定义为类方法。另外,如果需要继承,也可以定义为类方法。如下场景:假设我有一个学生类和一个班级类,想要实现的功能为:
执行班级人数增加的操作、获得班级的总人数;
学生类继承自班级类,每实例化一个学生,班级人数都能增加;
最后,我想定义一些学生,获得班级中的总人数。
class ClassTest(object):
    __num = 0

    @classmethod
    def addNum(cls):
      cls.__num += 1

    @classmethod
    def getNum(cls):
      return cls.__num

    # 这里我用到魔术函数__new__,主要是为了在创建实例的时候调用人数累加的函数。
    def __new__(self):
      ClassTest.addNum()
      return super(ClassTest, self).__new__(self)

class Student(ClassTest):
    def __init__(self):
      self.name = ''

a = Student()
b = Student()
print(ClassTest.getNum()))


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

class TimeTest(object):
    def __init__(self, hour, minute, second):
      self.hour = hour
      self.minute = minute
      self.second = second

    @staticmethod
    def showTime():
      return time.strftime("%H:%M:%S", time.localtime())
print(TimeTest.showTime())
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)
二、私有属性和私有方法在Python中,如果你想定义一个私有函数,你可以在函数名称前加上两个下划线__。这会触发一个名字改编(name mangling)的过程,使得这个函数在外部不容易被直接访问。这种机制的目的是为了“伪私有”,实际上是提供了一种弱保护措施来避免子类意外覆盖基类的方法。Python对于类的成员没有严格的访问控制限制,这与其他面向对象 语言有区别。关于私有属性和私有方法,有如下要点:
[*]1 通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public)。
[*]2 类内部可以访问私有属性(方法)
[*]3 类外部不能直接访问私有属性(方法)
[*]4 类外部可以通过 _类名__私有属性(方法)名 ”访问私有属性(方法)

#测试私有属性、私有方法
class Employee:
__company = "百战程序员" #私有.通过dir查到_Employee__company
def __init__(self,name,age):

   self.name = name
   self.__age = age#私有实例属性

def say_company(self):
   print("我的公司是:",Employee.__company)

   print(self.name,"的年龄 是:",self.__age)
   self.__work()
def __work(self): #私有实例方法,通过dir可查
    print("工作!好好工作,好好赚钱,娶个媳妇!")
p1 = Employee("高淇",32)
print(p1.name)
print(dir(p1))
p1.say_company()
print(p1._Employee__age)#通过这种方式进行调用


--------------------------------------------------------
高淇
['_Employee__age', '_Employee__company', '_Employee__work', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'say_company']
我的公司是: 百战程序员
高淇 的年龄 是: 32
工作!好好工作,好好赚钱,娶个媳妇!
32


三、装饰器@property@property 可以将一个方法的调用方式变成“属性调用”。 @property 主要用于帮助我们处理属性的读操作、写操作。对于某一个 属性,我们可以直接通过: emp1.salary = 30000使用场景:如上的操作读操作、写操作。但是,这种做法不安全。比如,我需 要限制薪水必须为 1-10000 的数字。这时候,我们就需要通过使用装 饰器 @property 来处理。class Person:
    def __init__(self, name, age):
      self._name = name# 使用下划线前缀表示私有变量
      self._age = age

    @property
    def name(self):
      """获取name属性的值"""
      return self._name

    @name.setter
    def name(self, value):
      """设置name属性的值"""
      if not isinstance(value, str):
            raise ValueError("name must be a string")
      self._name = value

    @property
    def age(self):
      """获取age属性的值"""
      return self._age

    @age.setter
    def age(self, value):
      """设置age属性的值"""
      if not isinstance(value, int) or value < 0:
            raise ValueError("age must be a non-negative integer")
      self._age = value

    def __str__(self):
      return f"Person(name={self.name}, age={self.age})"

# 使用示例
p = Person("Alice", 25)
print(p)# 输出:Person(name=Alice, age=25)

p.name = "Bob"# 修改name属性的值
print(p)# 输出:Person(name=Bob, age=25)
#
# p.age = 30# 修改age属性的值
# print(p)# 输出:Person(name=Bob, age=30)

# # 尝试设置非法值
# p.name = 123# 抛出ValueError异常:name must be a string
# p.age = -1# 抛出ValueError异常:age must be a non-negative integer

-----------------------------------------------------------------
Person(name=Alice, age=25)
Person(name=Bob, age=25)


属性和方法命名:1、_xxx :保护成员,不能用 from module import * 导入,只有类对象和子类对象能访问这些成员。(⚠️讲完模块再看)2、__xxx__ :系统定义的特殊成员 3、__xxx : 类中的私有成员,只有类对象自己能访问,子类对象也不能访问。(但,在类外部可以通过 对象名. _类名__xxx 这种特殊方式访问。Python不存在严格意义的私有成员)⚠️再次强调,方法和属性都遵循上面的规则。


四、关于None判断和总结None的解释⚠️None不是False,None不是0,None不是空字符串。None 和任何其他的数据类型比较永远返回False。


五、继承【重点】继承是面向对象三大特征之一。继承不是让我们去新发明、而是去改善。继承逻辑
#Python支持多重继承,一个子类可以继承多个父类。继承的语法格式如下:

class子类类名(父类1[,父类2,...]):
                类体


如果在类定义中没有指定父类,则默认父类是 object类 。也就是说, object 是所有类的父类,里面定义了一些所有类共有
的默认实现,比如: __new__()


1 子类不重写 __init__ ,实例化子类时,会自动调用父类定义的 __init__ 。 2 子类重写了 __init__ 时,实例化子类,就不会调用父类已经定义的 __init__ 3 如果重写了 __init__ 时,要使用父类的构造方法,可以使用 super 关键字,也可以使用如下格式调用
class person:
    def __init__(self,name,age,address):
      self.name = name
      self.age = age
      self.address =address
    def say_age(self):
      print(self.name,"的年龄是:",self.age)



class xiaoming(person):
      def __init__(self,name,age,address,gender):
            print("xiaoming的构造方法")
            person.__init__(self,name,age,address)#使用基类的方法进行优化,但是需要注意的是这里也要传self
            self.gender = gender


xm=xiaoming("小明",12,"辽宁","男")
xm.say_age()

【super】我们都知道,在子类中如果有与父类同名的成员,那就会覆盖掉父类里的成员。那如果你想强制调用父类的成员呢?使用super()函数!这是一个非常重要的函数,最常见的就是通过super调用父类的实例化方法__init__!语法:super(子类名, self).方法名(),需要传入的是子类名和self,调用的是父类里的方法,按父类的方法需要传入参数。class A:
    def __init__(self, name):
      self.name = name
      print("父类的__init__方法被执行了!")
    def show(self):
      print("父类的show方法被执行了!")

class B(A):
    def __init__(self, name, age):
      super(B, self).__init__(name=name)
      self.age = age

    def show(self):
      super(B, self).show()

obj = B("jack", 18)
obj.show()


六、类成员的继承和重写成员继承:子类继承了父类除构造方法之外的所有成员。 ⚠️(私有属性、私有方法也被继承) 2 方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类 的方法,也称为“重写”
# 定义一个父类
class Animal:
    def __init__(self, name):
      self.name = name

    def speak(self):
      raise NotImplementedError("子类必须实现这个方法")

# 定义一个子类,继承自Animal类
class Dog(Animal):
    def speak(self):
      return f"{self.name} says: Woof!"

# 定义另一个子类,也继承自Animal类
class Cat(Animal):
    def speak(self):
      return f"{self.name} says: Meow!"

# 使用子类
dog = Dog("Buddy")
cat = Cat("Whiskers")

# 调用speak方法,演示方法重写的效果
print(dog.speak())# 输出: Buddy says: Woof!
print(cat.speak())# 输出: Whiskers says: Meow!

多态
多态(polymorphism)是指同一个方法调用由于对象不同可能会 产生不同的行为。 比如:现实生活中,同一个方法,具体实现会完全不同。 比 如:同样是调用人“吃饭”的方法,中国人用筷子吃饭,英国人用 刀叉吃饭,印度人用手吃饭。 关于多态要注意以下2点: 1 多态是方法的多态,属性没有多态。 2 多态的存在有2个必要条件:继承、方法重写 classAnimal():

    def sout(self):
      print("动物叫了一下!")

class Dog(Animal):
    def sout(self):
      print("狗叫了一下!")

class cat(Animal):

    def sout(self):
      print("猫叫了一下!")


def common_animals(ami):
    ami.sout()


common_animals(Dog())
common_animals(cat())

--------------------------------
狗叫了一下!
猫叫了一下!


四、浅拷贝与深拷贝浅拷贝和深拷贝的区别是:浅拷贝只拷贝当前对象不会拷贝到当前对象的子对象,深拷贝是会拷贝当前的对象以及子对象import copy

class MobilePhone:
    def __init__(self, cpu):
      self.cpu = cpu

class CPU:
    pass

# 创建CPU对象
c = CPU()

# 创建MobilePhone对象,并将CPU对象作为参数传递
m = MobilePhone(c)

# 打印原始对象的ID
print("----浅拷贝-------")
m2 = copy.copy(m)# m2是新拷贝的另一个手机对象
print("m:", id(m))
print("m2:", id(m2))
print("m的cpu:", id(m.cpu))
print("m2的cpu:", id(m2.cpu))# m2和m拥有了一样的cpu对象
# m: 1452501984496
# m2: 1452503257776
# m的cpu: 1452501985216
# m2的cpu: 1452501985216


# 打印深拷贝后对象的ID
print("----深拷贝--------")
m3 = copy.deepcopy(m)
print("m:", id(m))
print("m3:", id(m3))
print("m的cpu:", id(m.cpu))
print("m3的cpu:", id(m3.cpu))# m
#----深拷贝--------
# m: 1452501984496
# m3: 1452503202160
# m的cpu: 1452501985216
# m3的cpu: 1452503654064

四、抽象类
抽象基类是Python中一种强大的工具,用于定义接口和规范,并确保类遵循指定的约定。它们在代码的类型检查、文档编写和设计模式实现中发挥着重要作用。本文详细介绍了抽象基类的概念、创建方法和应用场景,并提供了丰富的示例代码,希望可以帮助大家更好地理解和应用Python中的抽象基类。通过使用抽象基类,可以编写更加可靠、清晰和可维护的Python代码。# python
# -*- coding: utf-8 -*-
# @Time    : 2024/6/24
# @Author: solowang
# @Software: PyCharm
# @File    : 工厂模式.py
# @desc    :
from abc import ABCMeta, abstractmethod


# 创建Animal抽象类   ABCmeta是抽象类继承元类 [*]
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def do_say(self):
      pass


# 创建Dog类
class Dog(Animal):
    def do_say(self):
      print('Bhow Bhow!')


# 创建Cat类
class Cat(Animal):
    def do_say(self):
      print('Meow Meow!')


# 创建工厂类
class ForestFactory:
    def make_sound(self, object_type):
      return eval(object_type)().do_say()


if __name__ == '__main__':
    ff = ForestFactory()
    ff.make_sound('Cat')

longmarchw 发表于 2024-7-15 11:33

这是上课吗?{:1_918:} 现在编程都可以用 copilot助手辅助。基本功很快就能补齐。

laironggui 发表于 2024-7-15 13:40

这是啥意思?
页: [1]
查看完整版本: python 面向对象