多态、类属性和类方法
面向对象的三大特征
- 封装
- 将属性和方法书写到类里面操作即为封装
- 封装可以为属性和方法添加私有属性
- 继承
- 子类默认继承父类的所有属性和方法
- 子类可以重写父类属性和方法
- 多态
- 传入不同的对象,产生不同的结果
多态
了解多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
- 定义︰多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
- 好处︰调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
- 实现步骤:
- 定义父类,并提供公共方法
- 定义子类,并重写父类方法
- 传递子类对象给调用者,可以看到不同子类执行效果不同
体验多态
# 需求:警务人员和警犬一起工作,警犬分2种:追击敌人和追查毒品,携带不同的警犬,执行不同的工作
class Dog(object):
def work(self): # 父类统一的方法
print("指哪儿打哪儿...")
class ArmyDoy(Dog): # 继承Dog类
def work(self): # 子类重写父类同名方法
print("追击敌人...")
class DrugDog(Dog):
def work(self):
print("追查敌人...")
class Person(object):
def work_with_dog(self,dog):
dog.work()
# 创建对象,调用不同的功能,传入不同的对象,观察执行的结果
ad = ArmyDoy()
dd = DrugDog()
zhangsan = Person()
zhangsan.work_with_dog(ad)
zhangsan.work_with_dog(dd)
'''
追击敌人...
追查敌人...
'''
类属性和实例属性
类属性
- 设置和访问类属性
- 类属性就是类对象所拥有的属性,它被该类的所有实例对象所共有。
- 类属性可以使用类对象或实例对象访问。
class Dog(object):
color = 'red'
dog1 = Dog()
dog2 = Dog()
print(dog1.color)
print(dog2.color)
print(Dog.color)
'''
red
red
red
'''
类属性的优点:
- 记录的某项数据始终保持一致时,则定义类属性。
- 实例属性要求每个对象为其单独开辟一份内存空间来记录数据,而类属性为全类所共有,仅占用一份内存,更加节省内存空间。
修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。
class Dog(object):
color = 'red'
dog1 = Dog()
dog2 = Dog()
# 1.通过类修改类属性
Dog.color = 'green'
print(dog1.color)
print(dog2.color)
print(Dog.color)
print('---'*10)
# 2.通过对象修改类属性
dog1.color = 'yellow'
print(dog1.color)
print(dog2.color)
print(Dog.color)
'''
green
green
green
------------------------------
yellow
green
gre
# 2.通过对象修改类属性
dog1.color = 'yellow'
print(id(dog1.color))
print(id(dog2.color))
print(id(Dog.color))
'''
140507812252848
140507812252784
140507812252784
'''
类方法和静态方法
类方法
- 类方法的特点:
- 需要用装饰器**@classmethod **** 来标识其为类方法,对于类方法,第一个参数必须是类对象**,一般以cls作为第一个参数。
- 类方法使用场景
- 当方法中需要使用类对象(如访问私有类属性等)时,定义类方法
- 类方法一般和类属性配合使用
class Dog(object):
__color = 'red'
@classmethod
def get_color(cls):
return cls.__color
wangcai = Dog()
result = wangcai.get_color()
print(result) # red
静态方法
- 静态方法特点
- 需要通过装饰器**@staticmethod **** 来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象入(形参没有self/cls)。**
- 静态方法也能够通过实例对象和类对象去访问。
- 静态方法使用场景
- 当方法中既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性、类方法、创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗
class Dog(object):
@staticmethod
def info_print():
print('这是一个狗类,用于创建狗实例...')
wangcai = Dog()
# 静态方法既可以使用对象访问又可以使用类访问
wangcai.info_print()
Dog.info_print()
'''
这是一个狗类,用于创建狗实例...
这是一个狗类,用于创建狗实例...
'''
装饰器和注解
装饰器(Decorators)在Python中与Java中的注解(Annotations)有一些相似之处,它们都是一种元编程(Metaprogramming)的概念,允许程序员在代码中添加附加功能或元数据。
- 语法相似性:
- Python装饰器和Java注解都是通过特定的语法进行定义和应用。在Python中,装饰器使用@decorator_name的语法应用于函数类。在Java中,注解使用@AnnotationName的语法应用于类、方法、变量等元素。
- 功能相似性:
- 装饰器和注解都用于给函数或类添加额外的功能特定的行为。Python装饰器可以在不修改原函数或类的情况下,通过包装(wrapping)的方式加额外的逻辑。Java注解可以在不改变原有代码的情况下,为类、方法、变量等添加元。数据或额外信息。
- 元数据和运行时访问:
- 在Python中,装饰器可以提供运行时的元数据,例如记录函执行时间、权限检查等。在Java中,注解同样提供运行时的元数据,并且可以使用反射机制来获取注解信息。
- 内置装饰器和自定义注解:
- Python中有一些内置装饰器,如@staticmethod、@classmetho等,它们提供了常见的装饰功能。Java中也有一些内置注解,如@Override、@Deprecated,用于标记方法的重写或废弃状态。Python和Java都支持自定义装饰器和注解,允许开发者根据需要定义自己的装饰器或注解。
虽然装饰器和注解有一些相似之处,但也有一些重要的区别。例如,装饰器是在运行时动态地修改函数或类的行为,而Java。的注解通常是通过编译时处理器来处理的。此外,装饰器是Python中的一等公民,而Java的注解则具有更多的限制和用途。因此,在使用装饰器和注解时,需要根据各自语言的特性和需求进行适当的选择和使用。