python学习
类与对象
类的创建
- 创建类的语法
class 类名:
pass
class Student:
pass
print(id(Student)) # 2373708068384
print(type(Student)) # <class 'type'>
print(Student) # <class '__main__.Student'>
- 类的组成:
- 类属性
- 实例方法
- 静态方法
- 类方法
class Student:
place = 'China' # 直接写在类里面的变量,称为类属性
def __init__(self, name, age): # 初始化方法
self.name = name # self.name 实例属性
self.age = age # 同样 self.age 也是实例属性
# 实例方法 实例对应于 c++中的对象 在类里面的称方法,在类外面称函数
def eat(self):
print('干饭!')
@classmethod # 用 @classmethod 修饰,则该方法为 类方法
def book(cls):
print('类方法')
@staticmethod # 用 @staticmethod 修饰,则该方法为 静态方法
def walk(): # () 里不能写 self
print('静态方法')
对象的创建
- 对象的创建又叫 类的实例化
- 语法结构:对象 = 类名()
- 意义:有了实例,就可以调用类中的内容
# 需要用到前面创建的 Student 类
# 创建 Student 类的对象
stu1 = Student('wwj', 20)
print(id(stu1)) # 2205897665504
print(type(stu1)) # <class '__main__.Student'>
# 2205897665504 对应的十六进制就是 0x0000020199BF2BE0 所以输出的是对象的内存地址的十六进制
print(stu1) # <__main__.Student object at 0x0000020199BF2BE0>
# 类对象
print(id(Student)) # 2205889693360
print(type(Student)) # <class 'type'>
print(Student) # <class '__main__.Student'>
之所以能能清楚的创建哪个类的对象,是因为有个类指针指向要创建对象所属的 类
实例属性和实例方法
所创建的对象调用 实例属性 和 实例方法
# 创建 Student 类的对象
stu1 = Student('wwj', 20)
# 调用 实例属性
print(stu1.name) # wwj
print(stu1.age) # 20
# 调用 实例方法 的第一种方式 对象名.实例方法()
stu1.eat() # 干饭!
# 调用 实例方法 的第二种方式 类名.实例方法(所创建的对象)
Student.eat(stu1) # 干饭!
类属性、类方法、静态方法
- 类方法:类中 方法外 的变量称为类属性,被该类的所有对象所共享
stu1 = Student('wwj', 20)
stu2 = Student('sl', 20)
print(Student.place) # China
print(stu1.place) # China
print(stu2.place) # China
Student.place = 'Hunan'
print(Student.place) # Hunan
print(stu1.place) # Hunan
print(stu2.place) # Hunan
# 下面这种情况要特别注意
stu1.place = 'Hengyang'
print(Student.place) # Hunan
print(stu1.place) # Hengyang
print(stu2.place) # Hunan
# 我们发现 只有 stu1.place 是 Hengyang,其他的都是Hunan,注意,这里 stu1 调用的并不是类属性,而是动态绑定了一个属性,关于动态绑定属性后面会有介绍,也就是说stu1.place 指向的是新的一段存储空间。关于类属性的修改,只能通过类名调用类属性去修改
# 我们可以输出一些,就可以发现 stu1.place 的存储空间跟其他二者的存储空间不一致
print(id(Student.place)) # 1375226585456
print(id(stu1.place)) # 1375226554800
print(id(stu2.place)) # 1375226585456
- 类方法:使用@classmethod修饰的方法,使用 类名 直接访问的方法
Student.book() # 类方法
- 静态方法:使用@staticmethod修饰的主法,使用类名直接访问的方法
Student.walk() # 静态方法
本人试了试,发现 类方法 和 静态方法,都可以用 对象来调用,但是 实例方法 不能直接 用类名来调用实例方法,得传入一个 该类所对应的对象
动态绑定属性和方法
- 直接附加
- 动态绑定属性
stu1 = Student('wwj', 20)
stu2 = Student('sl', 20)
stu1.gender = '男'
print(stu1.name, stu1.age, stu1.gender) # wwj 20 男
# print(stu2.name,stu2.age,stu2.gender) AttributeError: 'Student' object has no attribute 'gender'
print(stu2.name, stu2.age) # sl 20
- 动态绑定方法
def func1():
print('动态绑定方法')
stu1 = Student('wwj', 20)
stu2 = Student('sl', 20)
stu1.show = func1 # func1 不用加() 方法名可以不一致,但是最好一致
stu1.show()
# stu2.show() AttributeError: 'Student' object has no attribute 'show'
面向对象的三大特征
封装
- 提高程序的安全性
- 将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度
- 在Python中没有专门的修饰符用于属性的私有,如果该属性(包括类属性和实例属性)不希望在 类的外部 被访问,前边使用两个”_”
- 被两个"_"修饰的属性,在类的外部不能直接被使用,但是还是有方法 可以使用到,格式: _类名__不想被类的外部访问的变量名
stu1 = Student('wwj', 20)
stu2 = Student('sl', 20)
# print(dir(stu1)) 查看stu1所有能够使用的属性和方法
# 对__修饰的属性的访问,一般不会给出代码提示
print(stu1._Student__age) # 20
print(stu1._Student__place) # China
继承
- 提高代码的复用性
- 如果一个类没有继承任何类,则默认继承object
- Python支持多继承
- 定义子类时,必须在其构造函数中调用父类的构造函数
- 语法格式:
class 子类类名(父类1,父类2):
pass
单继承:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + '的年龄是' + str(self.age))
class