1、类和对象
面向对象编程优点:易维护、易扩展、易复用,适合复杂系统,灵活方便。
对象指实际存在的事物,其通常包含两部分:属性和行为。一般使用变量表示对象的属性,用函数或方法表示对象的行为。
而类是指用来描述一组具有相同属性和行为的对象的模版,在现实世界中,先有对象后有类,而在计算机的世界中先有类后有对象。
2、类的定义
在python中通过关键字class定义类:(与Java相同)
class <类名>:
类属性1
···
类属性n
<方法定义1>
···
<方法定义n>
注:类名通常首字母大写,用驼峰命名法
类中通常包含一个初始化方法:__init__( )
回顾:Java中初始化方法的三个要求:
1、与类同名 2、无参数 3、无返回类型
类定义方法都有一个名为self的参数,且其必须是方法的第一个参数,表示当前对象 即该类对象。在方法中调用实例变量时要以self开头,表示当前对象的属性。
class Rectangle:
def __init__(self, width, height) :
self.width = width
self.height = height
def get_area(self):
return self.width * self.height
def get_perimeter(self):
return 2* (self.width+self.height)
3、类对象的创建
对象名 = 类名(参数列表)
参数列表主要与类中初始化函数__init__( )除self以外的参数匹配
创建对象后调用其方法和属性的格式为:
对象名.对象的属性
对象名.对象的方法()
紧接上文,我们创建对象:
rect_1 = Rectangle(3, 5)
print("矩形宽", rect_1.width)
print("矩形长", rect_1.height)
print("矩形面积", rect_1.get_area())
print("矩形周长", rect_1.get_perimeter())
4、类的属性
4.1 实例属性
实例属性是指在方法内部通过“self.属性名”定义的属性。实例属性在类的内部通过“self.属性名”来访问,在外部通过 “对象名.属性名” 来访问。实例属性一般在__init__()方法中初始化,但也可在其他实例方法中声明(但不建议哈)
class Student:
def __init__(self, name)
self.name = name
def self_major(self, major)
self.major = major
注意:对一个不存在的实例属性变量赋值会为该对象添加一个实例属性变量,但如果直接访问则会直接报错。
4.2 类属性
类属性变量是在类中所有方法之外定义的变量,可以在所有实例中共享,类属性通过“类名.类属性变量名”进行访问。
class Student:
count = 0
def __init__(self, name):
self.name = name
def set_major(self, major)
self.major = major
s1 = Student('张三')
s2 = Student('李四')
print(Student.count) # 这里调用类变量
5、类的方法
5.1 实例方法
与实例属性相同,在类的内部通过"self.方法名(参数)"来调用,在类的外部通过“对象名.类方法名”调用。若方法名前标注“__方法名”,则表示该方法属于私有方法,只允许在类的内部调用,在外部无法直接调用。
class Student:
def __init__(self, name)
self.name = name
def self_major(self, major)
self.major = major
def having_class(self, cousename):
print(self.name,"正在上课",cousename) # 在实例方法中调用实例变量也要用self.标明
5.2 类方法
类方法定义前一般添加@classmethod装饰器,第一个参数必须为类对象,参数通常为cls,表示当前类。与Java相同,类方法只能访问类变量,而不能访问实例变量。
使用类方法一般通过“类名.类方法名”进行访问。
class A:
name = 'A' # 类变量
@classmethod # 定义类方法
def show_classname(cls): #
print("The name is", cls.name)
A.show_class_name()
a = A()
a.name
进阶:装饰器:
# 装饰器
class Person:
def __init__(self, name = '未知',age =18):
self.name = name
self.age = age
@property
def age(self):
return self.__age
@age.setter
def age(self, age):
if age < 1 or age > 100:
print("错误")
else :
self.__age = age
@age.deleter
def age(self):
del self.__age
p1 = Person()
p1.age = 101
print(p1.age)
6、静态方法
Java中静态是否其实是用于区分变量与方法是否为实例或对象的关键词,但在python中静态方法主要作为一些工具方法使用,用装饰器:@staticmethod 声明
7、类的继承
在python中一个类可以继承一个或多个父类,子类可以继承父类的公有成员,但不能继承其私有成员。如果需在子类中调用父类的方法,则可通过内置函数“super().方法名”或“基类名.方法名()”的方式来实现。Java中不支持多重继承
语法格式:
class 子类名(父类1,父类2.....父类n):
类体
如果没有标准父类则默认为object,其为所有类的基类,同时可以省略小括号。
object类的所有方法都为__方法__(),常见的有创建函数__new__(),初始化函数__init__()
class Person:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def working(self):
print(self.name, "正在工作")
def show(self):
print(self.name)
print(self.age)
print(self.name)
class Student(Person):
def __init__(self, name="张三", age='20', sex='男', major='计算机'):
super().__init__(name, age, sex)
self.major = major
def show(self): # 子类重写父类方法
Person.show(self)
print(self.major)
student_1 = Student(major="软件工程")
student_1.show()
student_1.working()
多重继承时的调用顺序:
创建子类默认调用所有父类的创建方法new,但不会调用所有父类的初始化方法init
若子类没有提供初始化方法init,则默认调用第一个父类的初始化方法init;若子类提供了初始化方法,则默认不调用父类的初始化方法,此时,通常会在子类的初始化方法中显示调用父类的初始化方法,以确保父类初始化。
7、类方法重写
当父类的方法无法满足子类的要求,可以在子类中重写父类的方法,也就是在子类中写一个和父类方法名相同的方法。Java中也存在重写的概念,与之区别的概念有方法的重载,即在一个类中通过不同参数列表书写同名方法。重写与重载的区别在一个是子类与父类间的交互,一个是类之间方法的声明,python也支持重载。
以下是一个方法重写的例子:
class Person:
def __init__(self, same, age, sex):
self.name = name
self.age = age
self.sex = sex
def working(self):
print(self.name,"正在工作")
def show(self):
print("姓名",self.name)
print("年龄",self.age)
print("性别",self.sex)
class Student(Person):
def __init__(self, name='张三', age='20', sex='男', major='计算机'):
super().__init__(name, age, sex) # 显式初始化父类
self.major = major
def show(self): # 重写show方法
person.show(self)
print("专业", self.major)
student_A = Student(major='软件工程')
student_A.working()
student_A.show()
8、对象的复制
(1)赋值符号“=”使得引用相同
(2)copy模块的copy函数是浅复制:只复制当前对象,不会复制对象内部的其他对象
(3)copy模块的deepcopy函数是深复制:即全复制,此时对象两者独立