摘要:构造函数构造函数参数列表在使用类创建对象时自动调用。类是从一堆对象中抽取相同的属性及方法得出的,抽象类就是从一堆类中抽取相同的属性及方法得出的。抽象类不能实例化对象。
1.构造函数
构造函数:__init__(参数列表) :在使用类创建对象时自动调用。
注意:如果自己不写构造函数,系统默认也会加上一个空的构造函数。
对象属性的优先级高于类属性,当对象调用属性时,如果有对象属性时,先获取对象属性的值;如果没有对象属性,会去找同样名字的类属性;如果没有同样名字的类属性,返回一个错误。
class Person(): # 直接写在class中的属性叫类属性(可以通过类名直接调用) # name = "" # age = 0 # 默认的构造函数(在init方法中的属性叫对象属性) # __init__函数没有返回值,不能写return # def __init__(self): # pass # 自己重新写构造函数时,只能更改参数列表及函数体,不能写return这条语句 # def __init__(self): # print("我显示的是init函数") def __init__(self, name, age, weight=30.0): print("小兔子乖乖") # 对象属性(定义在构造函数中的属性为对象属性) self.name = name self.age = age self.weight = weight # 建议:一个类中最好只有一个init函数,如果写了多个,程序不会报错, # 但是只会执行最后一个写的init函数 def eat(self): print("person--eat") def sleep(self, hours): print("我睡了%d小时" % hours) # 建议使用关键字 实例化对象 per1 = Person(name="Lily", age=30, weight=50.0)2.self和__class__
self:当前类的实例对象,但是在类中用self表示。3.析构函数
哪个对象调用带有self参数的方法时,self就指向哪一个对象。__class__: 代表当前类的类名。
self:不是关键字,换成其他的词语也可以,只要类中的成员方法至少有一个形参即可,第一个形参就代表当前类的实例对象
析构函数:__del__() : 释放对象时调用,销毁对象时调用。
class Person(): # 构造函数 def __init__(self, name): self.name = name def __del__(self): print("析构函数" + self.name) per1 = Person("tom") per2 = Person("lucy") per3 = Person("lily") # del per3.name 删除对象属性 # del per3 # 手动删除优先级高 先删除lily 然后执行类里的析构函数,系统的自动回收 def fun1(): per4 = Person("Json") # 局部变量 print(per4.name) fun1() # Json 析构函数Json 用完函数后 per4 被析构函数回收4.__str__函数
在使用print打印对象时会自动调用,这个方法是给用户使用的,是描述对象的方法。
class Person(): def __init__(self, name, age, sex): self.name = name self.sex = sex self.age = age # 可以在类中重新写__str__方法 # 要求必须有返回值,返回值类型str类型 def __str__(self): sexStr = "" if self.sex == 1: sexStr = "女" elif self.sex == 0: sexStr = "男" return "姓名为%s, 年龄为%d,性别为%s" %(self.name, self.age, sexStr)5.访问限制
私有属性子类不能继承,子类的对象不能使用
实例对象不能直接访问私有属性__age,因为python解释器把__age私有属性变成了_Person__age, 我们就可以通过_Person__age访问私有属性__age。强烈建议:不要这么干
class Person(): def __init__(self, name, age, weight, height): # 公有属性:能够在当前类、当前类的实例对象、子类中均能使用 self.name = name # 私有属性: 只能在当前类中使用 # 格式:__属性名(只在属性名前面加两个下划线) self.__age = age # 格式:__变量名__:在python中属于特殊变量,可以直接访问,类似公有属性 self.__weight__ = weight # 格式: _变量名:在python中能够正常访问,类似公有属性,但是,当我们 # 看到这种属性时,把它当成是私有属性使用。 # _变量名(虽然我现在能直接访问并使用,但请把我当成私有属性,不要用 # 对象直接访问) self._height = height # set方法:赋值 def setAge(self, age): if age < 0: self.__age = 20 else: self.__age = age # get方法: 取值 def getAge(self): return self.__age + 20 def setName(self, name): self.name = name def getName(self): return self.name6.继承
class Animal(): def __init__(self, name, color, age): self.name = name self.age = age # 私有属性 self.__color = color def run(self): print(self.__color) print("run") def eat(self): print("eat") class Cat(Animal): def __init__(self, name, age, color, miao): # 调用父类的__init__方法 # 父类名称.__init__(self, 根据父类形参赋值实参) Animal.__init__(self, name, color, age) # 使用super关键字调用init方法(同上) # super(Cat, self).__init__(name, color, age) # 子类可以有自己独有的属性 self.miao = miao7.多重继承和多继承
单继承:一个子类只有一个父类8.类方法及静态方法
多重继承:子类有父类,父类又有父类 : 父类->子类->子子类。。。。。
多继承: Son -> Father,Mother
注意:如果父类们中的方法名相同,默认调用小括号中排在前面的父类中的方法(就近原则)
类方法 @classmethod
类方法一般来说使用类名调用。
类方法类和对象均能调用,但是不管是类还是对象调用,cls都代表类;比如当前例子中,cls就代表Person,cls不是关键字,使用其他形参名称也可以,总之,类方法的第一个形参就代表类。静态方法 @staticmethod
静态方法一般来说不是给对象是用的,一般使用类名调用
静态方法就是一个普通函数,不会默认需要传参数
类和对象均能调用,但一般使用类名调用
class Person(): # 对象方法,使用实例对象调用 def eat(self): print("eat") # 类方法 @classmethod @classmethod def play(cls, a, b): print("类方法", a+b) print(cls) # 静态方法 @staticmethod @staticmethod def run(num1, num2): print(num1 + num2)9.动态添加属性及方法及__slots__属性
from types import MethodType class Person(): def run(self): print("run") pass # 动态添加属性 per1 = Person() per1.name = "Lily" print(per1.name) # 动态添加方法 def say(self): print("say") # MethodType(函数名称, 当前实例对象的名称) # 把当前的实例对象传递给函数的第一个形参 per1.saying = MethodType(say, per1) per1.saying()
思考:如果我们要限制动态添加属性或方法的个数及名称怎么办?比如我们只能动态添加name及age属性,run方法。为了达到要求,python允许在定义类时,定义一个特殊的属性__slots__属性变量,__slots__属性可以限制动态添加的属性及方法的名称。
__slots__ :使用元组的方式赋值
注:__slots__定义的属性只对当前类有效,对它继承的子类无效;
如果子类中也定义了__slots__属性,这样定义的属性的个数为子类本身的内容加上父类中定义的内容。
class Student(): __slots__ = ("name", "age", "run") pass stu1 = Student() stu1.name = "Tom" # stu1.weight = 56.7 # 错误,不允许添加 def run(self, a, b): print("run", a+b) stu1.run = MethodType(run, stu1) stu1.run(2,3)10.@property
@property 装饰器
@property: 可以使对象通过点方法访问私有属性。
class Person(): def __init__(self, name, age): # 公有属性 self.name = name # 私有属性 self.__age = age @property def age(self): return self.__age @age.setter def age(self, age): if age < 0: age = 1 self.__age = age per1 = Person(name="二胖", age=1) # 如果属性为公有属性,对象可以直接调用进行更改或使用 # 这样,不安全,数据可以直接被重新赋值,而且没有任何限制条件。 # 相当于调用set方法,现在调用的是加了@age.setter装饰器的方法 per1.age = 99 # 相当于调用get方法,现在调用的是加了@property装饰器的方法 print(per1.age)11.运算符重载
class Person(): def __init__(self, num): self.num = num # 打印对象时调用 def __str__(self): return "目前num为:" + str(self.num) # 运算符重载 def __add__(self, other): return Person(self.num + other.num) def __mul__(self, other): return Person(self.num * other.num) p1 = Person(100) print(p1) p2 = Person(266) print(p2) print(p1 + p2) # p1.__add__(p2) __add__(self, other) Person(111) Person(111) print(p1 * p2) __init__: 构造函数 __del__:析构函数 __str__:打印对象 __add__:加运算 __mul__:乘运算 __sub__:减运算 __mod__:余运算 __div__:除运算 __pow__:幂运算12.抽象类
在开发中,我们遇到的所有事物都是对象,对象是通过类创建的。但是不是所有的类都是用来描述对象的。如果一个类中没有足够的条件信息来描述一个具体的事物/对象,而需要其他具体的类来辅助他,那么,这样的类我们称之为抽象类。抽象类中可以有抽象方法,一般包含抽象方法的类都是抽象类。
抽象方法可以不包含任何方法实现的代码,只有一个方法名字,但是,在子类中要求必须实现该抽象方法,否则,子类也为抽象类。类是从一堆对象中抽取相同的属性及方法得出的,抽象类就是从一堆类中抽取相同的属性及方法得出的。
抽象类不能实例化对象。
1、定义抽象类
在定义抽象类之前,我们需要导入模块abc中的ABCMeta类(抽象基类的元类)(Metaclass for defining Abstract BaseClass)。在定义抽象类时,我们需要在代码中加入 metaclass=ABCMeta,指定该类的元类为ABCMeta元类:创建一个类的类。
抽象类不能实例化对象。
抽象类一般都用作父类。2、定义抽象方法
在定义抽象方法之前,我们需要导入模块abc中的abstractmethod类。
在定义抽象方法时,我们需要在方法前面加上@abstractmethod修饰词。
因为抽象方法一般不需要在抽象类中实现,我们只需要在抽象方法的函数体中写一条pass语句即可。3、实现类
实现类为抽象类的子类。
如果实现类不实现父类(抽象类)中的抽象方法,那么该类也是抽象类;
如果实现类实现了父类(抽象类)中的抽象方法,那么该类就是普通类,可以实例化对象。
from abc import ABCMeta, abstractmethod # 定义抽象类 class Animal(metaclass=ABCMeta): # 定义属性 def __init__(self, color): self.color = color # 对象方法 def eat(self): print("Animal--eat") # 定义抽象方法 @abstractmethod def play(self): pass # 创建实现类(以一个抽象类为父类) class Cat(Animal): def __init__(self, color, name): Animal.__init__(self, color) self.name = name # 子类实现父类的抽象方法 def play(self): print("cat--play") cat1 = Cat(color="black", name="旺财") print(cat1.color)13.接口
真正的接口中不能定义变量,接口中只能有抽象方法。1.什么是接口 interface,接口都是当作父类使用。
子类实现接口中的抽象方法。
在python中没有interface这个关键字,我们目前所写的接口只是通过抽象类仿写,
所以,目前,接口可以认为就是一个类,一个只包含抽象方法并且不能实例化对象的类。其子类如果想要实例化对象,必须实现接口中所有的抽象方法。2.为什么要使用接口?
接口本身就是一系列方法的声明,一些特殊方法的集合,一个接口中只有方法的声明,但是没有方法的实现,这些特殊的方法要在不同的类之间进行不同的实现。接口本身是用于封装代码的。例子:鸟类和昆虫类都有飞行的行为,功能相同,但实现内容不同,二者如果抽象出一个类不太方便,但可以抽象一个接口,用于飞行行为的封装。
3.注意:一般在接口中只有方法的声明,没有方法的实现。在接口中不能出现变量。
from abc import abstractmethod # 定义接口 class Interface: # 仿写接口 # 定义抽象方法 @abstractmethod def fly(self): pass # ... # 定义接口的实现类 class Bird(Interface): def __init__(self, leg): self.leg = leg def egg(self): print("鸟生蛋") def fly(self): print("小鸟飞的高") class Insect(Interface): def __init__(self, leg): self.leg = leg def spawn(self): print("昆虫产卵") def fly(self): print("昆虫飞的低") b1 = Bird(2) b1.fly() i1 = Insect(6) i1.fly()14.多态
面向对象的三大特征: 封装,继承,多态
多态:一种事物的多种形态,子类可以认为是父类的不同形态的实现python是弱类型语言,声明变量时,不要求数据类型,根据赋值的类型去确定该变量的类型。c,Java强类型语言,声明变量时,已经确定该变量的数据类型,如果赋值的类型与声明的类型不一致,程序会报错。在强类型语言中:子类对象可以强转为父类类型的对象,但父类类型的对象不能强转为子类类型的对象。在强类型语言中:子类对象可以强转为父类类型的对象,父类类型的对象也能强转为子类类型的对象。
class Animal(): def __init__(self, name): self.name = name def eat(self): print(self.name + "eat") class Cat(Animal): def __init__(self, name): Animal.__init__(self, name) def run(self): print(self.name + "run") class Dog(Animal): def __init__(self, name): Animal.__init__(self, name) class Person(): # def feedAnimalCat(self, cat): # print("人喂了" + cat.name) # def feedAnimalDog(self, dog): # print("人喂了" + dog.name) def feedAnimal(self, animal): print("人喂了" + animal.name) per = Person() cat1 = Cat("喵") # per.feedAnimalCat(cat1) dog1 = Dog("汪") # per.feedAnimalDog(dog1) per.feedAnimal(cat1) per.feedAnimal(dog1)
class Animal(object): def run(self): print("animal is running") class Dog(object): def run(self): print("dog is running") class Cat(object): def run(self): print("cat is running") def run_twice(animal): animal.run() animal.run() run_twice(Animal()) run_twice(Cat()) run_twice(Dog()) class Tortoise(Animal): def run(self): print("Tortoise is running slowly...") run_twice(Tortoise())
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/41602.html
摘要:看起来好像是废话,它还有一个补充的说明,在函数式编程中要避免状态变化和使用可变对象。函数式编程的特点在中,函数即对象,例如声明一个函数之后,你可以调用其属性。 ...
摘要:一面向对象编程。是一门面向对象的编程语言,通过对象实现对方法的调用。面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。对于面向对象语言,重要的概念是类和实例。 一、preface 面向对象编程OOP:object oriented programming。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。Python是一门面向对象的编程语言,...
摘要:语料库是由文本构成的数据集通过提供现成的文本数据来辅助文本处理。那么可以用来做什么呢我自己是一名从事是不错的入门选项。大数据和人工智能是机器学习和的主要开发语言。 Python培训有哪些内容?很多零基础学员不知道Python软件是干什么用的?Python软件是Python工程师编写代码时所需...
摘要:如果初学者接触的第一门语言是,学习曲线则会平滑得多,掌握一些基本语法和内置的数据结构,已经可以上手写一些小工具或者小型应用。如果你的学习时间充足,我的建议是一定要学数据结构和算法。 前言 Python是最容易入门的编程语言,没有之一。如果初学者接触的第一门语言是C或者C++,对他们来说最难的不是语法,而是容易出现内存泄漏、指针等问题。有时候排查这些问题对初学者的打击很大,尤其是没掌握排...
摘要:反对者在某些领域对此予以否认。下面再引用一段来自维基百科中关于的历史。类的更严格的定义是由某种特定的元数据所组成的内聚的包。类还可以有运行时表示形式元对象,它为操作与类相关的元数据提供了运行时支持。 在开始部分,请看官非常非常耐心地阅读下面几个枯燥的术语解释,本来这不符合本教程的风格,但是,请看官谅解,因为列位将来一定要阅读枯燥的东西的。这些枯燥的属于解释,均来自维基百科。 1、问题...
阅读 3174·2021-11-25 09:43
阅读 3392·2021-11-11 16:54
阅读 793·2021-11-02 14:42
阅读 3709·2021-09-30 09:58
阅读 3631·2021-09-29 09:44
阅读 1236·2019-08-30 15:56
阅读 2069·2019-08-30 15:54
阅读 2934·2019-08-30 15:43