一、类与实例
类是抽象的,约定了未来实例应该有的内容,是实例的模版
实例是具体的,有具体数据,调用类则生成实例,实例的内容依赖于类
python
class People:
def __init__(self,name):
self.name = name
p = People("张三")
print(p.name)
二、魔法函数
以双下划线开头和结尾的函数称为魔法函数
魔法函数不需要自己调用
__init__ 用于初始化self
__str__ 返回实例的字符串表示,自定义内容的字符串
__len__ 使用len函数 返回实例对应的长度:自定义返回的数值
__eq__ 使用 == 触发
__ne__ 使用 != 触发
__gt__ 使用>触发
__ge__ 使用>=触发
__lt__ 使用<触发
__le__ 使用<=触发
__add__ 使用+触发
__sub__ 使用—触发
__mul__ 使用*触发
__truediv__ 使用/触发
__floordiv__ 使用//触发
__mod__ 使用%触发
__divmod__ 使用div(x,y)触发
例子如下:
python
class MyClass:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name},{self.age}"
def __len__(self):
return len(self.name)
def __gt__(self, other):
return self.age > other.age
def __ge__(self, other):
return self.age >= other.age
def __lt__(self, other):
return self.age < other.age
def __le__(self, other):
return self.age <= other.age
def __eq__(self, other):
return self.age == other.age
def __ne__(self, other):
return self.age != other.age
def __add__(self, other):
return self.age + other.age
def __sub__(self, other):
return self.age - other.age
def __mul__(self, other):
return self.age * other.age
def __truediv__(self, other):
return self.age / other.age
def __floordiv__(self, other):
return self.age // other.age
def __mod__(self, other):
return self.age % other.age
def __divmod__(self, other):
return divmod(self.age, other.age)
s0 = MyClass("zs", 18)
print(s0)
print(len(s0))
s1 = MyClass("ls", 20)
print(s1 > s0, s1 >= s0, s1 < s0, s1 <= s0)
print(s0 == s1, s0 != s1)
print(s0 + s1, s0 - s1, s0 * s1, s0 / s1, s0 // s1, s0 % s1, divmod(s0, s1))
三、三大特性
(一)封装
将数据与操作用类进行封装,例子如下:
数据 state color与操作 is_open change_state get_color set_color用类Light进行封装
python
class Light:
def __init__(self):
self.state = False
self.color = ["蓝色","红色","白色"]
self.current = 0
def is_open(self):
return self.state
def change_state(self):
self.state = not self.state
def get_color(self):
return self.color[self.current]
def set_color(self):
self.current += 1
if self.current == len(self.color):
self.current = 0
l0 = Light()
print(l0.is_open())
l0.change_state()
print(l0.is_open())
(二)继承
单继承
继承使用关键字class
和super()
来实现,一个类可以继承另一个类的属性和方法,被继承的类称为父类或基类,继承的类称为子类或派生类。
子类可以访问父类的属性和方法,也可以添加自己的属性和方法。
例如,定义一个Person
类作为父类,包含了name
和age
属性,以及walk()
方法:
python
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return f"姓名:{self.name},年纪:{self.age}"
def walk(self):
print("走路")
然后,定义一个SuperPerson类作为子类,继承了Person
类的属性和方法,同时添加了自己的fly()
方法以及skill属性:
python
class SuperPerson(Person):
def __init__(self,name,age,skill):
# 继承父类的属性,super()是固定格式
super().__init__(name,age)
self.skill = skill
def __str__(self):
return f"{super().__str__()},技能:{self.skill}"
def fly(self):
print("会飞")
现在,创建一个Student
对象,并调用继承自父类的walk()
方法和子类的fly()
方法:
python
sp1 = SuperPerson("ljr",18,"变绿")
print(sp1)
sp1.walk()
sp1.fly()
通过继承,子类可以复用父类的代码,避免重复编写相同的属性和方法。
多继承
多继承是指一个类可以同时继承多个父类的特性和方法。多继承的语法非常简单,只需要在定义类时在类名后面添加括号,括号中写上要继承的所有父类的名称,用逗号隔开即可。
python
class MoveAble:
def __init__(self, speed):
self.speed = speed
def move(self):
print(f"i can move, my speed is {self.speed}")
def __str__(self):
return "我是移动类"
class SpeakAble:
def __init__(self, language):
self.language = language
def speak(self):
print(f"i can speak {self.language}")
def __str__(self):
return "我是说话类"
class AttackAble:
def __init__(self, skill):
self.skill = skill
def attack(self):
print(f"使用{self.skill}发起攻击")
def __str__(self):
return "我是攻击类"
class Person(MoveAble, SpeakAble):
def __init__(self, name, speed, language):
# super().__init__() 会执行第一个父类
# super().__init__(speed)
# 通过类名表名 需要初始化哪个父类 必须传入self
MoveAble.__init__(self, speed)
SpeakAble.__init__(self, language)
self.name = name
def show(self):
print(f"my name is {self.name}")
def __str__(self):
return "我是人类"
p0 = Person("小张", 50, "汉语")
p0.show()
p0.move()
p0.speak()
class ATM(Person, AttackAble):
def __init__(self, name, speed, language, skill):
Person.__init__(self, name, speed, language)
AttackAble.__init__(self, skill)
def __str__(self):
return f"我是奥特曼类"
atm0 = ATM("赛罗", 1000, "光之语言", "赛罗光线")
atm0.show()
atm0.move()
atm0.speak()
atm0.attack()
print(atm0)
# 多继承 mro: method(方法) retrieval(检索) order(顺序)
# Python3 使用广度优先
print(ATM.mro())
(三)多态
多态是面向对象编程中的一个概念,它表示同一种操作可以作用于不同的对象,产生不同的结果。简单来说,多态就是一个接口(方法)具有多种实现方式。
在Python中,多态是通过方法重写(override)和方法重载(overload)实现的。
方法重写是指子类重新定义了父类中已经存在的方法,使得子类可以根据自己的需求对方法进行不同的实现。
方法重载是指在一个类中定义了多个同名但参数不同的方法,可以根据不同的参数类型和数量来调用不同的方法。
以下是一个使用多态的示例:
python
class Animal:
def sound(self):
pass
class Dog(Animal):
def sound(self):
print("Woof!")
class Cat(Animal):
def sound(self):
print("Meow!")
def make_sound(animal):
animal.sound()
dog = Dog()
cat = Cat()
make_sound(dog) # 输出:Woof!
make_sound(cat) # 输出:Meow!
在上面的例子中,我们定义了一个Animal
父类,以及Dog
和Cat
子类,它们都重写了父类的sound()
方法。然后,我们定义了一个make_sound()
函数,接受一个Animal
对象作为参数,并调用其sound()
方法。当我们传入Dog
对象时,会调用Dog
子类的sound()
方法,输出狗叫声;当我们传入Cat
对象时,会调用Cat
子类的sound()
方法,输出猫叫声。这就是多态的体现,相同的方法名可以根据不同的对象产生不同的结果。
多态提高了代码的灵活性和可扩展性,使得我们可以通过统一的接口实现不同的功能。
四、抽象类
抽象类是一个特殊的类,内部可以编写抽象方法,也可编写普通实例方法,抽象类不能直接实例化。抽象类子类必须实现抽象类中的抽象方法。
python
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def walk(self):
pass
def eat(self):
print(f"可以吃")
class Dog(Animal):
def walk(self):
print("摇摇尾巴")
dog = Dog()
dog.walk()
dog.eat()
五、实例属性与实例方法
实例属性是定义在类的实例对象上的属性。它们属于实例对象本身,并且每个实例对象都有自己的一份独立的属性。实例属性可以在类的方法中使用,也可以通过实例对象来访问和修改。
以下是定义实例属性的示例:
python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)
print(person1.name) # 输出: Alice
print(person2.age) # 输出: 30
person1.age = 26 # 修改实例属性
print(person1.age) # 输出: 26
实例方法是绑定到实例对象上的方法。实例方法可以访问实例对象的属性,并且可以在方法内部对属性进行操作。实例方法可以在类的实例对象上调用。
以下是定义实例方法的示例:
python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hello, my name is {self.name}!")
person = Person("Alice", 25)
person.greet() # 输出: Hello, my name is Alice!
在上述示例中,greet
方法是一个实例方法,它可以访问实例对象的属性name
。在调用greet
方法时,会自动将实例对象作为self
参数传递给方法。通过self.name
可以访问实例对象的name
属性并输出。
六、类属性与类方法
类属性是定义在类上的属性,它属于整个类而不是类的实例对象。类属性在所有实例对象之间共享,并且可以通过类名或实例对象来访问。
类方法是定义在类上的方法,它可以通过类名或实例对象来调用。类方法的第一个参数通常被命名为cls
,用于表示当前类对象。
以下是定义类属性和类方法的示例:
python
class Person:
count = 0 # 类属性
def __init__(self, name):
self.name = name
Person.count += 1 # 访问类属性并进行修改
@classmethod
def get_count(cls):
return cls.count # 访问类属性
person1 = Person("Alice")
person2 = Person("Bob")
print(Person.get_count()) # 输出: 2
person3 = Person("Charlie")
print(person3.get_count()) # 输出: 3
在上述示例中,count
是一个类属性,它记录了创建的Person
实例对象的数量。在__init__
方法中,每创建一个实例对象,都会通过Person.count
对类属性进行修改。
get_count
是一个类方法,通过使用装饰器@classmethod
来定义。在类方法中,我们可以访问类属性count
。
类方法可以通过类名或实例对象来调用。通过Person.get_count()
可以获得类方法的返回值,通过person3.get_count()
也可以获得同样的结果。
需要注意的是,类方法无法访问实例属性,但可以通过参数传递实例对象来访问实例属性。
七、静态方法
静态方法是定义在类中的方法,它不与类的实例对象进行交互,也不与类属性进行交互。静态方法可以通过类名或实例对象来调用,但它不会自动接收任何参数。
以下是定义静态方法的示例:
python
class MathUtils:
@staticmethod
def add(x, y):
return x + y
@staticmethod
def multiply(x, y):
return x * y
print(MathUtils.add(3, 5)) # 输出: 8
print(MathUtils.multiply(3, 5)) # 输出: 15
在上述示例中,add
和multiply
都是静态方法,通过使用装饰器@staticmethod
来定义。静态方法可以直接通过类名来调用,无需先创建实例对象。静态方法内部可以访问其他静态方法或静态属性,但无法访问实例方法或实例属性。
静态方法通常用于执行与类相关但不依赖于实例对象的操作。它们可以提高代码的可读性和可维护性,因为它们清楚地表明它们不依赖于实例状态。