Python | 编程思想
一、类与对像的创建
1. 类的组成
类属性、实例方法、静态方法、类方法
Class Student: pass
Student为类的名称,每个单词的首字母大写,其余小写
直接写在类里的变量,称为类属性
实例方法
def eat(self): print("吃")
静态方法
@staticmethoddef method(): print("staticmethod进行修饰为静态方法,不能使用self")
在类之外定义的称之为函数,在类之内定义的称之为方法
静态方法进行修饰,不能使用self
类方法
@classmethoddef cm(cls): print("classmethod进行修饰为类方法,使用cls")
init初始化方法
def __init__(self,name,age): self.name = name self.age = age
self.name称为实体属性,进行了一个赋值操作,将局部变量的name的值赋给实体变量
2. 对象的创建
对象的创建又称为类的实例化
语法:
实例名 = 类名()
意义:有了实例,就可以调用类中的内容
总结
类属性:类中方法外的变量称之为类属性,被该类的所有对象所共享
类方法:使用@classmethod修饰的方法,使用类名直接访问的方法
静态方法:使用@staticmethod修饰的方法,使用类名直接访问的方法
Student.native_pace # 访问类属性
Student.cm() # 调用类方法
Student.sm() # 调用静态方法
class Student: native_pace='安徽' @classmethod def cm(cls): print("classmethod进行修饰为类方法,使用cls") @staticmethod def method(): print("staticmethod进行修饰为静态方法,不能使用self") print(Student.native_pace) Student.cm() Student.method()
面向对象的三大属性
封装:提高程序的安全性
继承:提高代码的复用性
多态:提高代码的可扩展性和可维护性
1.封装
封装:提高程序的安全性
将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度
在python中没有专门的修饰符用于属性的私有,如果该属性不需要在类对象外部被访问,前面使用两个“_”
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() # print(stu.name) #print(dir()) # print(stu._Student__age)
年龄不希望在类的外部被调用,所以使用两个“_”
在类的外部可以通过_student__age进行访问
2.继承
语法格式:
class 字典类名(父级1,父级2):
如果一个类都没有继承任何类,则默认继承object
class Person(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) self.stu_no=stu_no class Teacher(Person): def __init__(self,name,age,teachofyear): super().__init__(name,age) self.teachofyear=teachofyear stu=Student("张三",20,"1001") teacher=Teacher("李四",34,10) stu.info() teacher.info() 打印结果: 张三 20 李四 34
多继承
class A(object): pass class B(object): pass class C(A,B): pass
3.方法重写
如果子类对继承父类的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写
子类重写后的方法中可以通过super().xxx()调用父类中被重写的方法
class Person(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) self.stu_no=stu_no def info(self): super().info() print("学号",self.stu_no) class Teacher(Person): def __init__(self,name,age,teachofyear): super().__init__(name,age) self.teachofyear=teachofyear def info(self): super().info() print("教龄:",self.teachofyear) stu=Student("张三",20,"1001") teacher=Teacher("李四",34,10) stu.info() print("-------") teacher.info()
打印结果:
张三 20
学号 1001
-------
李四 34
教龄: 10
4.object类
object类是所有类的父类,因此所有类都有object类的属性和方法;
内置函数dir()可查看指定对象所有属性;
object有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数str(),
经常用于print()方法,帮我们查看对象的信息,所以我们经常会对__str__()进行重写
class Student: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return "我的名字是{0},今年{1}岁".format(self.name,self.age) stu=Student("张三",20) print(dir(stu)) print(stu) print(type(stu))
打印结果:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
我的名字是张三,今年20岁
<class '__main__.Student'>
5.多态
多态就是“具有多种形态”,它指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法
class Animal: def eat(self): print("动物会吃") class Dog(Animal): def eat(self): print("狗吃骨头") class Cat(Animal): def eat(self): print("猫吃鱼") class Peason(): def eat(self): print("人吃五谷杂粮") #定义一个函数 def fun(obj): obj.eat() #开始调用函数 fun(Cat()) fun(Dog()) fun(Animal()) print("----------") fun(Peason()) # 打印结果 猫吃鱼 狗吃骨头 动物会吃 ---------- 人吃五谷杂粮
6.特殊属性和特殊方法
特殊方法__add__()
stu1 ='张三' stu2 ='李四' s=stu1+stu2 print("两个对象相加方法一",s) s=stu1.__add__(stu2) print("两个对象相加方法二",s) # 打印结果 两个对象相加方法一 张三李四 两个对象相加方法二 张三李四
特殊方法__len__()
class Student: def __init__(self,name): self.name=name def __len__(self): return len(self.name) stu1=Student("Python") print("stu1()中Python的长度",len(stu1)) lst=[11,22,33,44] print("列表的长度",len(lst)) print("列表的长度",lst.__len__()) # 打印结果 stu1()中Python的长度 6 列表的长度 4 列表的长度 4
特殊方法__new__() 、特殊方法__init__()
class Person(object): def __init__(self,name,age): self.name=name self.age=age 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): print("__init__被调用了,self的id值为:{0}".format(id(self))) self.name=name self.age=age print("object这个类对象的id值为:{0}".format(id(object))) print("Person这个类对象的id值为:{0}".format(id(Person))) p1=Person("张三",20) print("p1这个Person类的实例对象的id:".format(id(p1))) # 打印结果 Person这个类对象的id值为:52902248 __new__被调用执行了,cls的id值为:52902248 创建的对象的id为43581072 __init__被调用了,self的id值为:43581072 object这个类对象的id值为:257496144 p1这个Person类的实例对象的id:
__new__方法的第一个参数是这个类,而其余的参数会在调用成功后全部传递给__init__方法初始化,所以,__new__方法(第一个执行)先于__init__方法执行,
比较两个方法的参数,可以发现__new__方法是传入类(cls),而__init__方法传入类的实例化对象(self),而有意思的是,__new__方法返回的值就是一个实例化对象(ps:如果__new__方法返回None,则__init__方法不会被执行,并且返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法),结合到代码,也就是__new__的返回值正是__init__中self。
小结: __new__和__init__相配合才是python中真正的类构造器。
其中,__new__()不是一定要有,只有继承自object的类才有,该方法可以return父类(通过super(当前类名, cls).__new__())出来的实例,或者直接是object的__new__出来的实例。值得注意的是,在定义子类时没有重新定义__new__()时,Python默认调用该类父类的__new__()方法来构造该类实例,如果该类父类也没有重写__new__(),那么将一直追溯至object的__new__()方法,因为object是所有新式类的基类。如果子类中重写了__new__()方法,那么可以自由选择任意一个其他的新式类。
可见,当类中同时出现__new__()和__init__()时,先调用__new__(),再调用__init__(),具体的执行过程为:
1. 调用实例对象代码xiaoming = Student('xiaoming',175);
2. 传入name和height的参数,执行Student类的__new__()方法,该方法返回一个类的实例,通常会用父类super(Student,cls).__new__(cls),__new__()产生的实例即__init__()的self;
3. 用实例来调用__init__()方法,进行初始化实例对象的操作。
可以看到,python中__new__()与__init__()的区别,
1.首先用法不同,__new__()用于创建实例,所以该方法是在实例创建之前被调用,它是类级别的方法,是个静态方法;
而 __init__() 用于初始化实例,所以该方法是在实例对象创建后被调用,它是实例级别的方法,用于设置对象属性的一些初始值。
由此可知,__new__()在__init__() 之前被调用。如果__new__() 创建的是当前类的实例,会自动调用__init__()函数,通过return调用的__new__()的参数cls来保证是当前类实例,如果是其他类的类名,那么创建返回的是其他类实例,就不会调用当前类的__init__()函数。
2.其次传入参数不同
__new__()至少有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别;
__init__()至少有一个参数self,就是这个__new__()返回的实例,__init__()在__new__()的基础上完成一些初始化的操作。
3.返回值不同
__new__()必须有返回值,返回实例对象;
__init__()不需要返回值。
https://www.cnblogs.com/jayliu/p/9013155.html
https://blog.csdn.net/m0_64118193/article/details/124612710