Python学习笔记(5)
文章目录- 前言
- 一、类与对象
- 1、类的创建
- 2、类的组成
- 3、对象的创建
- 4、类的调用
- 5、类属性和类方法
- 二、类的封装、继承和多态
- 1.封装
- 2.继承
- 3.object类
- 4.多态
- 三、类的特殊方法和属性
- 1.特殊方法
- 2.特殊属性
- 3.new 与init 的区别
- 三、变量的赋值与拷贝
- 1.变量的赋值
- 2.拷贝
- 四、模块
- 五、python中的包
- 总结
前言
此片笔记主要是关于python的面向对象
一、类与对象
- 类是多个类似事物组成的群体的统称。能够帮助我们快速理解和判断我们快速理解和判断事物的性质
- 数据类型->不同数据类型属于不同的类,使用内置函数查看数据类型
- python中一切皆对象
创建语法:
class Student: #Student是类名,类名可以由一个或多个单词组成,最好每个单词的首字母大写
pass #暂时想不出写啥,pass用来占位
因为python中一切皆对象,所以可以输出:
print(id(Student)) print(type(Student)) print(Student)
2、类的组成运行结果:
类的组成有:类属性、实例方法、静态方法、类方法
#类的创建
class Student: #Student是类名,类名可以由一个或多个单词组成,最好每个单词的首字母大写
one_define = '直接写在类里的变量称为类属性'
def __init__(self, name, age): #为构造方法,用于对象初始化对象实例化后自动调用
self.name = name #slef.name 称为实例属性,进行了一个复制操作
self.age = age #将局部变量的值赋给实例属性
def eat(self): #实例方法
print('self->请注意得写,这个是实例方法')
print('在类里面定义的为方法,在类之外定义的成为函数')
@staticmethod
def methond(): #静态方法
print('使用了staticmethond修饰,是静态方法')
@classmethod
def cm(cls): #类方法
print('使用了classmethod修饰,是类方法')
print('cls->要求传一个')
3、对象的创建
对象的创建又称为类的实例化,有了实例,就可以调用类中的类容
stul = Student('传入某名字,后面是年龄', 20)
#stul 是实例对象,Student 是类对象
print(id(stul))
print(type(stul))
print(stul)
4、类的调用结合上面代码运行结果:
代码:
stul.eat()
print(stul.name)
print(stul.age)
#换一种调用方法
print('- - - - - 第二种调用方法 - - - - -')
Student.eat(stul) #传入自身->self
# 类名.方法名(类的对象)-->实际上就是方法定义处的 self
5、类属性和类方法运行结果:
类属性:类中方法的变量称为类属性,被该类所有对象所共享
类方法:使用 @classmethod 修饰的方法,使用类名直接访问的方法
静态方法:使用 @staticmethod 修饰方法,使用类名直接访问的方法
代码:
stu1 = Student('传入某名字,后面是年龄', 20)
stu2 = Student('传入某名字,后面是年龄', 30)
print(Student.one_define)
Student.one_define = '随便改一个'
print(Student.one_define)
Student.cm() #调用时候不需要传参数
Student.methond() #静态方法
运行结果:
PS:动态绑定:一个Student类可以创建多个实列对象,每个实例对象的属性值不同
代码:
stu1 = Student('张三', 20)
stu2 = Student('李四', 20)
#动态绑定性别属性
stu2.gender = '女'
print(stu1.name, stu1.age)
print(stu2.name, stu2.age, stu2.gender)
def show():
print("定义在类外的函数")
stu1.show = show
stu1.show()
#stu2没有绑定.所以无法调用show,而stu1绑定了,于是可以调用
二、类的封装、继承和多态 1.封装运行结果:
封装: 提高程序安全性->将数据(属性)和行为(方法)包装到类对象中
在方法内部对属性进行类对象的外部调用方法,无需关心方法的具体实现
如果该属性不希望在类对象外被访问,前面使用两个"_"
封装的实现:
class Student:
def __init__(self, name, age):
self.name = name
self.__age = age #年龄不希望在类外被使用,所以加了两个下划线
def show(self):
print(self.name, self.__age) #但可以在类内调用
stu = Student("张三", 20)
stu.show()
#在类外调用不了age
print(stu.name)
print(dir(stu)) #查找类有哪些属性
print(stu._Student__age) #在类外通过_Student__age 进行访问
2.继承运行结果:
class 子类类名(父亲1,父亲2,…):
如果一个类没有继承任何类,则默认继承object类
python支持多继承,定义子类时,必须在其构造函数中调用父类的构造函数
实现方式:
class Person(object): #可以不写object
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name, self.age)
class Student(Person):
def __init__(self, name, age, stu_no):
super().__init__(name, age) #super()函数是调用父类的一个方法
self.stu_no = stu_no
def info(self):
super().info()
print(self.stu_no)
class Teacher(Person):
def __init__(self, name, age, teaching):
super().__init__(name, age)
self.teaching = teaching
def info(self):
super().info()
print("教龄:", self.teaching)
stu = Student("张三", 20, '100')
tea = Teacher("李四", 40, '15')
stu.info()
tea.info()
3.object类运行结果:
PS. 方法重写:如果子类对继承父类的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写,子类重写后的方法中可以通过super().xx()调用父类中被重写的方法
4.多态object是所有类的父亲
object有一个_str_()方法,用于返回一个对于"对象的描述",对应于内置函数str()经常用于print()方法,帮助我们查看对象的信息,所以我们经常会对str()进行重写
即便不知道一个变量所引用的对象到底是是那么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用那个对象中的方法
代码:
class Animal(object):
def eat(self):
print("动物的都会吃什么?")
class Cat(Animal):
def eat(self):
print("猫吃鱼")
class Dog(Animal):
def eat(self):
print("狗吃肉骨头")
class Person(object):
def eat(self):
print("人吃五谷杂粮")
def fun(obj):
obj.eat()
fun(Animal())
fun(Cat())
fun(Dog())
fun(Person())
#Person虽然没有继承Animal,但是里面也有eat函数,所以fun也可以调用
三、类的特殊方法和属性 1.特殊方法运行结果:
__ dict__() : 或的对象或实例所绑定的所有属性和方法的字典
代码:
class A:
pass
class B:
pass
class D(A):
pass
class C(A, B):
def __init__(self, name, age):
self.name = name
self.age = age
x = C('Amy',20)
print(x.__dict__) #实例对象的属性字典
print(C.__dict__) #类对象的属性字典
print(x.__class__) #输出的是对象所属
print(C.__bases__) #C类的父亲类型的元素
print(C.__base__) #离C类最近的一个基类
print(C.__mro__) #类的层次结构
print(A.__subclasses__()) #查看子类,子类的列表
2.特殊属性运行结果:
__ len__() : 通过重写__len__()方法,让内置函数len()的参数可以是自定义类型
__ add__() : 通过重写__add__()方法,可使用自定义对象具有“+”功能
__ new__() : 用于创建对象
__ init__() : 对创建的对象进行初始化
代码:
class Student:
def __init__(self, name):
self.name = name
def __add__(self, other):
return self.name + other.name
def __len__(self):
return len(self.name)
stu1 = Student('Amy')
stu2 = Student('Sam')
s = stu1 + stu2 #实现了两个对象的加法运算(因为再Student类中编写了__add__()特殊方法
c = stu1.__add__(stu2) #和上行同理
print(s)
print(c)
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(len(lst)) #这个len是内置函数的len
print(lst.__len__()) #内置的,和上行一样
print(len(stu1)) #输出的是对象的长度
3.new 与init 的区别运行结果:
代码:
class Person(object):
def __new__(cls, *args, **kwargs):
print("__new__()被调用执行了,cls的id值为:{0}".format(id(cls)))
obj = super().__new__(cls)
print('创建的对象的id为:{0}'.format(id(obj)))
return obj
def __init__(self, name, age):
self.name = name
self.age = age
print('__init__()被调用了,self的id值为:{0}'.format(id(self)))
print('object这个类对象的id为:{0}'.format(id(object)))
print('Person这个类对象的id为:{0}'.format(id(Person)))
#创建Person类实例对象
p1 = Person('Amy', 20)
print('p1这个Person类的实例对象的id为:{0}'.format(id(p1)))
#从结果推断出,在__new__()中创建的obj这个对象就是self和p1
三、变量的赋值与拷贝 1.变量的赋值运行结果:
PS.可以分析一下路径-.-
变量的赋值操作:只是形成两个变量,实际上还是指向同一个对象
演示代码:
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self, cpu, disk):
self.cpu = cpu
self.disk = disk
#变量的赋值
cpu1 = CPU()
cpu2 = cpu1
print(cpu1)
print(cpu2)
#根据结果可以发现地址是一样的
2.拷贝运行结果:
浅拷贝:python中的拷贝一般是指浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象于拷贝对象会引用同一个子对象
深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象有不相同
ps.没有特殊说明都是浅拷贝
演示代码:
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self, cpu, disk):
self.cpu = cpu
self.disk = disk
cpu1 = CPU()
cpu2 = cpu1
#类的浅拷贝
disk = Disk() #创建一个硬盘类的对象
computer = Computer(cpu1, disk) #创建一个计算机类的对象
#浅拷贝
import copy
computer2 = copy.copy(computer)
print(computer, computer.cpu, computer.disk)
print(computer2, computer2.cpu, computer2.disk)
#运行结果发现地址相同(->指针指向同一位置)不确定
#深拷贝
computer3 = copy.deepcopy(computer)
print(computer, computer.cpu, computer.disk)
print(computer3, computer3.cpu, computer3.disk)
#运行结果发现地址不一样
四、模块运行结果:
可以是python库中的,也可以自己写
模块中可以有很多个函数,还可以包含很多个类、语句
而项目中有很多个模块,而n多个模块组成python程序
自定义模块
新建名.py文件 (创建一个python file)
导入模块->import / form import
如何导入自己写的自定义模块
导入报错怎么办?->目录夹->右键->Make Directory as->Source Root
五、python中的包以主程序方式运行:
if name == ‘main’:
print(‘???’)
ps.只有当点击运行XX此文件时,才会执行
包是一个分层次的目录结构,它将一组功能相近的模块阻止在一个包中
包含__init__.py文件的目录称为包,目录通常不包含__init__.py文件
包的导入:
import 包名.模块名
导入带有包的模块时注意事项:
import 包名
import 模块 #使用import方式导入时,只能跟包名或者模块名
使用from可以导入包、模块、函数变量
eg:
from pageagel import modual_A
from pageagel.modual_A import a
‘’’
#python package->创建一个包
#Directory->是一个目录
‘’’
eg:
import pageagel.modual_A as ma #取了个别名ma
然后可以直接用print(ma.a)调用 这个a是包中的东东
python中常用的内置模块(偷个懒)
第三方模块的安装以及使用
1、第三方模块的安装:(在线安装方式)
window + R ->打开[运行]->输入cmd->然后输入pip install 模块名
完成安装后,输入python输入查看是否安装成功,然后就可以使用了
2、第三方模块的使用:
import 模块名
总结
大概就这些了,python中和类有关的



