文章目录

  • 简介
  • 专业术语
  • 对象的属性
  • 类的定义
    • 类的实例化
    • 类成员的可见性
  • 类的属性
    • 实例属性
    • 私有属性
    • 特殊属性
  • 类的方法
    • 成员方法
    • 私有方法
    • 类方法
    • 静态方法
    • 属性方法
  • 类的特殊方法
    • `__init__`构造方法
    • `__del__`析构方法
    • `__str__`
    • `__new__`
    • `__call__`
    • `__reduce___`
  • 类的继承
    • 派生类的定义
    • 派生类构造函数
    • 判断类的继承
  • 类的多继承
    • 多继承简介
    • 多继承查找顺序
  • 类的多态
    • 什么是多态
    • 多态实例
  • 反弹机制

简介

Python从设计之初就已经是一门面向对象的语言, 面向对象编程三大特性如下:

  • 封装: 隐藏实现细节,使代码模块化

  • 继承: 扩展已存在的类来实现代码重用,避免重复编写相同的代码

  • 多态: 封装和继承的目的都是为了实现代码重用, 而多态是为了实现接口重用,使得类在继承和派生的时候能够保证任何一个类的实例都能正确调用约定好的属性和方法

专业术语

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 方法: 类中定义的函数。
  • 类变量: 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。
  • 数据成员: 类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 方法重写: 如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写。
  • 局部变量: 定义在方法中的变量,只作用于当前实例的类。
  • 实例变量: 在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
  • 继承: 即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
  • 实例化: 创建一个类的实例,类的具体对象。
  • 对象: 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

对象的属性

在python中, 每个对象都有三个属性:

  • ID: 对象的地址, ID相同则表示同一对象
  • 类型(type)
  • 数值

类的定义

类是一种抽象数据类型,是对现实世界的一类数据及其操作的封装

类实例化后,可以使用其属性,创建一个类后,可以通过类名访问其类属性

如下所示, 定义一个含有三个属性的person类, 分别是ID(身份证号)、name(姓名)、nationality(国籍)

其中所有人的身份证号码都是不一样的,且不允许直接通过类或实例来访问或随意修改

import uuidclass Person:nationality = "China"#类的初始化def __init__(self, name):  self.name = nameself.__id = str(uuid.uuid1())def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" %(self.name, self.nationality, self.__id))

类的实例化

import uuidclass Person:nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" % (self.name, self.nationality, self.__id))user = Person('henry')  #创建一个类实例化对象user
user.hello() #输出Hello, I am henry, I come from China, My ID is cea8b568-4f53-11ed-a7de-00e04c8c73bb

类成员的可见性

Python中默认所有的成员都是公有成员,但私有成员是以两个下划线开头的名字表示私有成员,私有成员不允许直接访问,只能通过内部方法进行访问,私有成员也不允许被继承

Python中通过在类变量、实例变量、类方法、实例方法前加__前缀,可以将其对外进行隐藏,变为类的私有变量或函数

由于Python中内置变量或函数使用__作为前后缀,因此不推荐私有的变量或函数在前后缀都用__,而是只在前缀用__

Python类维护了一个用于保存类的数据的字典,字典内部Python将私有成员改名为_ClassName__variable,因此在类外通过访问私有变量新的名称可以访问相应的私有变量, 如下代码所示:

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" % (self.name, self.nationality, self.__id))if __name__ == "__main__":bauer = Person("Bauer")print(bauer.__dict__) #输出存放私有成员的字典print(bauer._Person__id) #输出该对象的person类的ID# 输入如下:
# {'name': 'Bauer', '_Person__id': 'ed496846-94c7-11e9-80c4-5ce0c5e8bcf0'}
# ed496846-94c7-11e9-80c4-5ce0c5e8bcf0

类的属性

直接定义在class下的属性是叫公有属性或类属性,类属性是类的所有实例对象共同所有的

类属性可以使用ClassName.VariableName访问,在实例方法内部也可以使用self.VariableName进行访问

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" % (self.name,self.nationality,self.__id))def sayHello(self):print("Hello,I come from %s" % self.nationality)if __name__ == "__main__":bauer = Person("Bauer")bauer.sayHello() #Hello,I come from Chinajack = Person("Jack")print(Person.nationality, bauer.nationality, jack.nationality) #输出China China Chinabauer.nationality = "USA"print(Person.nationality, bauer.nationality, jack.nationality) #输出China USA ChinaPerson.nationality = "Germany"print(Person.nationality, bauer.nationality, jack.nationality) #Germany USA Germany

在上述代码中, 将类属性 nationality 修改为 “Germany” 时,并没有修改实例 bauernationality 属性。因此,实例 bauernationality 属性的值仍然是 “USA”。

在 Python 中,如果实例有一个与类属性同名的属性,则实例的属性会覆盖类属性。例如,当你在类外面使用 bauer.nationality = "USA" 时,你为实例 bauer 创建了一个名为 nationality 的属性,值为 “USA”。这个属性会覆盖类属性 nationality,因此在使用 bauer.nationality 访问实例属性时,会返回 “USA” 而不是 “Germany”

实例属性

实例属性又称成员属性或成员变量,是类的每个实例对象单独持有的属性, 实例属性必须在类的__init__方法中进行声明

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = name  #name属于实例属性self.__id = str(uuid.uuid1())def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" % (self.name,self.nationality, self.__id))if __name__ == "__main__":bauer = Person("Bauer")jack = Person("Jack")print(bauer.name, jack.name) #输出"Bauer Jack"

若要访问实例属性, 只能通过实例对象访问, 若通过类访问则会报错, 如下所示

print(Person.name)

私有属性

私有属性和实例属性必须在__init__方法中进行声明,但私有属性的属性名需要以双下划线__开头, 例如上述Person中的__id属性

私有属性是一种特殊的实例属性,只允许在实例对象的内部访问, 且不能被子类继承

私有属性可以通过成员方法或是<实例对象._类名__私有变量名>的方式来访问

import uuid class Person(object):nationality = "China"def __init__(self, name):self.name = name #实例属性self.__id = str(uuid.uuid1())  #私有属性def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" %(self.name, self.nationality, self.__id))def get_id(self):return self.__idif __name__ == "__main__":bauer = Person("Bauer")bauer.hello()print(bauer._Person__id) #访问bauer成员的私有属性IDprint(bauer.get_id()) #通过成员方法get_id()访问私有属性ID

特殊属性

Python的类中有一些内置的、特殊的属性,其名称以双下划线__开头且以双下划线__结尾。特殊属性不是私有属性,可以在类的外部通过实例对象去直接访问,如下是常见的特殊属性

  • __doc__:类的描述信息。

  • __module__:对象定义所在的模块名。

  • __class__:当前操作的对象对应的类名。

  • __dict__:一个字典,保存类的所有的成员(包括属性和方法)或实例对象中的所有成员属性

实例对象.__dict__类.__dict__ 的值是不同的,实例对象.__dict__的值中只包含成员属性和私有属性,类.__dict__的值中包含类的类属性和所有方法

类的方法

成员方法

成员方法可以通过类的实例或类名调用,但使用类名时需要手动传入一个实例对象作为 self 参数。

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" %(self.name, self.nationality, self.__id))if __name__ == "__main__":bauer = Person("Bauer")bauer.hello() #通过类的实例对象调用Person.hello(bauer) #通过类名调用#两次输出的内容一致:Hello, I am Bauer, I come from China, My ID is 5beff5b1-500e-11ed-b861-00e04c8c73bb

私有方法

私有方法是以双下划线__开头的成员方法

私有方法只能在实例方法内部访问,且不能被子类继承;私有方法的第一个参数也必须是当前实例对象本身,通常写为self

前后加双下划线的命名方式用于Python内置的方法,不推荐自定义方法使用。

如果开发者以前后加双下划线的方式命名成员方法,则相应成员方法是公有的

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def __hello(self):  # 私有方法print("Hello, I am %s, I come from %s, My ID is %s" % (self.name,self.nationality, self.__id))def say_hello(self):  # 成员方法/实例方法self.__hello()if __name__ == "__main__":bauer = Person("Bauer")bauer.say_hello() #输出Hello, I am Bauer, I come from China, My ID is 5beff5b1-500e-11ed-b861-00e04c8c73bb

类方法

类方法是以@classmethod来装饰的成员方法,要求第一个参数必须是当前类, 通常写为cls

类方法可通过实例对象进行访问,还可以直接通过类名去访问

类方法只能访问类属性,不能访问实例属性,因此第一个参数传递的是代表当前类的cls,而不是表示实例对象的self

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def __hello(self):  # 私有方法print("Hello, I am %s, I come from %s, My ID is %s" % (self.name,self.nationality, self.__id))def say_hello(self):  # 成员方法/实例方法self.__hello()@classmethoddef get_nationality(cls):  # 类方法return cls.nationalityif __name__ == "__main__":bauer = Person("Bauer")print(bauer.get_nationality()) #通过实例对象调用类方法print(Person.get_nationality()) #通过类名调用类方法

静态方法

静态方法是以@staticmethod来装饰的成员方法

静态方法通常通过类名进行访问,也可以通过类的实例对象进行访问

静态方法已经与类没有任何关联,因此定义静态方法不要求必须传递实例对象或类参数

静态方法对参数没有要求,因此可以任意给静态方法定义参数,如果给静态方法定义表示当前类的参数(cls),那么就可以访问类属性;如果给静态方法定义了表示当前类的实例对象的参数(self),那么就可以访问实例属性;如果没有给静态方法定义当前类参数或当前实例参数,那么就不能访问类或实例对象的任何属性

import uuidclass Person(object):sum = 0nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())Person.sum += 1@staticmethoddef add(a, b):  # 静态方法return a + b@staticmethod  # 静态方法,内部使用类变量def counter():return Person.sum@staticmethoddef get_counter(cls):  # 静态方法,传递当前类return cls.sumif __name__ == "__main__":bauer = Person("Bauer")print(bauer.add(1, 2)) #通过实例对象调用静态方法print(Person.add(1, 2)) #通过类名调用静态方法print(Person.counter())print(Person.get_counter(Person)) #调用需传递类参数

属性方法

属性方法是以 @property 装饰的成员方法,用来访问实例属性。属性方法的第一个参数必须是当前实例,且必须有返回值

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def __hello(self):  # 私有方法print("Hello, I am %s, I come from %s, My ID is %s" %(self.name,self.nationality, self.__id))def say_hello(self):  # 成员方法/实例方法self.__hello()@classmethoddef get_nationality(cls):  # 类方法return cls.nationality@staticmethoddef add(a, b):  # 静态方法return a + b@propertydef id(self):return self.__idif __name__ == "__main__":bauer = Person("Bauer")print(bauer.id)

类的特殊方法

Python的类中有一些内置的、特殊的方法,其名称是以双下划线__开头且以双下划线__结尾。特殊方法不是私有方法,可以在类的外部通过实例对象去直接访问,且都有着各自特殊的意义

__init__构造方法

__init__方法是类构造函数,是类的特殊的方法,在创建类对象时自动调用,不能有返回值

__init__方法的第一个参数必须是创建的实例本身,通常推荐使用self。类的实例属性、私有属性必须在__init__方法进行声明

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())print(self.name, "__init__")if __name__ == "__main__":bauer = Person("Bauer") #输出"Bauer __init__"

__del__析构方法

__del__是类的析构方法,当对象在内存中被释放,会自动触发执行__del__方法,如实例对象的作用域退出时,或者执行 del 实例对象操作

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())print(self.name, "__init__")#定义析构方法def __del__(self):print(self.name, "__del__")if __name__ == "__main__":bauer = Person("Bauer") #输出"Bauer __init__"del bauer  #删除实例对象,触发析构函数,输出"Bauer __del__"

__str__

若类中定义了__str__方法,那么在打印对象时默认输出__str__方法的返回值,否则会打印出实例对象的内存地址

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())print(self.name, "__init__")def __del__(self):print(self.name, "__del__")def __str__(self):return "name: %s, nationality: %s, id: %s" % (self.name,self.nationality, self.__id)if __name__ == "__main__":bauer = Person("Bauer")   print(bauer) #输出内容如下:
# Bauer __init__
# 输出name: Bauer, nationality: China, id: 27c26af1-508a-11ed-899f-00e04c8c73bb
# Bauer __del__

__new__

其实在python中, __init__并不是真正的构造函数,__new____init__才是真正的构造函数

当我们在对类进行实例化的时候, __new__方法会在__init__方法前被执行, 会创建并返回一个新的实例对象传给__init__

在下面的例子中, 我们把类demo进行实例化对象为a, 那么在这个过程中, 类demo是如何确定它的实例对象会是a的呢?

这是因为__new__方法返回了这个值, 而这个值就是a, 最后python解析器将这个返回值告诉给__init__方法, 在__init__方法中的参数self其实就是这个a, 因为self代表的是类的对象

class demo():def __init__(self,arg,kwarg): #定义属性并初始化self.arg = argself.kwarg = kwargdef Output(self):print(self.arg)print(self.kwarg)a = demo("NMSL","WSND") #实例化
a.Output() #调用类中的Output方法

__new__方法常用于单例设计模式, 它是由object基类提供的内置静态方法

  • 让类创建的对象, 在内存中只有唯一的一个实例
  • 每一次实例化生成的对象, 其内存地址是相同的
class demo(object):ins = Nonedef __new__(cls):if cls.ins == None:cls.ins = super().__new__(cls)return cls.insa = demo()
b = demo()
print(a) #0x000001CE34C96FA0>
print(b) #0x000001CE34C96FA0>

__call__

类中定义__call__方法时,类对象实例可以作为一个函数去调用

import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def __call__(self, *args, **kwargs):print("name: ", self.name, "args: ", *args)def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" %(self.name, self.nationality, self.__id))if __name__ == "__main__":bauer = Person("Bauer")bauer(26) #将实例对象看成函数来传参进行调用,输出:"name:  Bauer args:  26"

__reduce___

在 Python 中,类的 __reduce__ 方法是一个特殊方法,用于描述对象的可序列化表示。当你使用内置的序列化函数(如 pickle.dumps)将对象序列化时,会调用对象的 __reduce__ 方法

__reduce__ 方法必须返回一个元组,元组中包含两个元素

  • 第一个元素是一个调用对象的构造函数,它用于在反序列化时创建新的对象。
  • 第二个元素是一个包含对象参数的元组,它用于在反序列化时传递给对象的构造函数
import pickle
shellcode = "list1 = [1,2,3,4]"class A(object):def __reduce__(self):return (exec,(shellcode,))#当实例对象被序列化后,则会调用特殊方法__reduce__,所以下列代码相当于pickle.dumps((exec,(shellcode,)))
ret = pickle.dumps(A())print(ret)
#输出:b'\x80\x04\x95-\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x04exec\x94\x93\x94\x8c\x11list1 = [1,2,3,4]\x94\x85\x94R\x94.'pickle.loads(ret)
print(list1)
#输出[1,2,3,4]

类的继承

派生类的定义

Python中类的继承按照父类中的方法是否已实现可分为两种:

  • 实现继承: 直接继承父类的属性和已定义并实现的方法
  • 接口继承: 仅继承父类类的属性和方法名称, 子类必须自行实现方法的功能

若根据继承父类的个数来分类, 又可分为两种:

  • 单继承: 只继承一个父类
  • 多继承: 继承多个父类

派生类构造函数

派生类的构造函数需要显式调用父类的构造函数,对父类的属性成员进行初始化,调用父类的构造函数时需要显式传递实例对象self

什么是显示调用和隐式调用? —— 在python使用3+23*2时,您似乎没有显式地调用任何方法,但实际上您调用了它,因为它们的实现方式是调用(3).__add__(2)(3).__mul__(2)。因此,您隐式地调用这些方法

子类需要在自己的__init__方法中的第一行位置调用父类的构造方法, 以下有两种方法, 在上述代码的注释中也进行了具体描述

  • super.(子类名, self).__init__(父类构造参数)
  • 父类名.__init__(self,父类构造参数)

如下代码所示, Teacher类和Student类都继承了Person类, 也就是说Teacher类和Student类是Person类的子类或派生类, 而Person类是Teacher类和Student类的父类、基类或超类

Teacher和Student对Person的继承属于实现继承,且是单继承

Teacher类和Student类都继承了Person类的name和age属性, 以及talk()walk()方法, 并扩展了自身的属性和方法

Teacher类和Student类可以在自己的类定义中重新定义父类Person的方法, 这种我们称为方法重写

class Person(object):def __init__(self, name, age):self.name = nameself.age = agedef walk(self):print('%s is walking...' % self.name)def talk(self):print('%s is talking...' % self.name)class Teacher(Person):def __init__(self, name, age, level, salary):super(Teacher, self).__init__(name, age)  #派生类调用父类构造函数的第一种方法:super.(子类名, self).__init__(父类构造参数)self.level = levelself.salary = salarydef teach(self):print('%s is teaching...' % self.name)class Student(Person):def __init__(self, name, age):Person.__init__(self, name, age)   #派生类调用父类构造函数的第二种方法:父类名.__init__(self,父类构造参数)def study(self):print('%s is studying...' % self.name)

判断类的继承

  • isinstance: 判断一个类对象是否是类的对象或者是类的子类对象
  • issubclass: 判断一个类是否是某个类的子类
class Person(object):def __init__(self, name, age):self.name = nameself.age = agedef walk(self):print('%s is walking...' % self.name)def talk(self):print('%s is talking...' % self.name)class Student(Person):def __init__(self, name, age):Person.__init__(self, name, age)   #派生类调用父类构造函数的第二种方法:父类名.__init__(self,父类构造参数)def study(self):print('%s is studying...' % self.name)if __name__ == '__main__':Tom = Student('tom',10)print(isinstance(Tom,Person))  #判断类对象Tom是否是Person类的子类对象或类对象,返回Trueprint(isinstance(Tom,Student)) #判断类对象Tom是否是Student类的子类对象或类对象,返回Trueprint(issubclass(Student,Person)) #判断Student类是否是Person类的子类,返回True

类的多继承

多继承简介

Python支持多层父类继承, 子类会继承父类以及父类的父类所有的属性和方法

在多继承时, 使用的super()函数只会调用第一个父类的属性方法, 若想调用特定父类的构造函数, 只能使用父类名.__init__这种方式调用

若在多个继承的父类中有相同的方法名, 而在子类未使用显示调用父类的方法, Python会根据继承顺序从左至右搜索查找父类中是否包含方法。

class B():def __init__(self):print("class B")def hello(self):print('hello, class B')class C():def __init__(self):print("class C")def hello(self):print('hello, class C')class D(B, C):def __init__(self):super(D,self).__init__()  #调用第一个父类(B)的构造函数print("class D")if __name__ == "__main__":d = D()d.hello()  #调用父类B的hello(),而没有调用父类C的hello()#输出内容:
# class B
# class D
# hello, class B

多继承查找顺序

类的属性__mro__或者方法mro()都能打印出类的继承顺序,super()在执行时查找MRO列表,到列表当前位置的类中去查找其下一个类,也就是说为了实现继承, python会在MRO列表从左到右开始查找父类, 直到找到第一个匹配属性的类为止

super是MRO中的一个类。MRO全称Method Resolution Order,代表类的继承顺序。对于定义的每一个类,Python会计算出一个方法解析顺序(MRO)列表,MRO列表是一个简单的所有基类的线性顺序列表

  • 子类会先于父类被检查
  • 多个父类会根据它们在列表的顺序被检查
  • 如果对下一个类存在两个合法的选择,选择第一个父类
class B():def __init__(self):print("class B")def hello(self):print('hello, class B')class C():def __init__(self):print("class C")def hello(self):print('hello, class C')class D(B, C):def __init__(self):super(D,self).__init__()  #调用第一个父类(B)的构造函数print("class D")if __name__ == "__main__":print(D.mro())  #输出[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]

类的多态

什么是多态

接口的所有子类必须实现接口中定义的所有方法;接口的各个子类在实现接口中同一个方法时,具体的代码实现各不相同,即为多态

多态实例

多态通常是通过继承接口的方式实现的,虽然Python中没有接口这个概念,但Python中可以通过在一个成员方法体中抛出一NotImplementedError异常来强制继承接口的子类在调用接口方法前必须先实现接口方法

举个例子,我们定义了一个名为 Shape 的类,用于表示形状。这个类中有一个方法 area 用于计算形状的面积,但是并没有为这个方法实现具体的代码逻辑。这样,当我们尝试调用 Shape 类的 area 方法时,就会抛出 NotImplementedError 异常,告诉调用者这个方法尚未实现

class Shape:def area(self):raise NotImplementedErrorclass Rectangle(Shape):def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightclass Circle(Shape):def __init__(self, radius):self.radius = radiusdef area(self):return 3.14 * self.radius **

反弹机制

Python中反射机制是通过hasattrgetattrsetattrdelattr四个内置函数实现的,四个内置函数不仅可以用在类和对象中,也可以用在模块等

  • hasattr(obj,key): 返回bool值, 判断某个成员或者属性在不在类或对象中
  • getattr(obj,key,default=xxx): 获取类或者对象的成员或属性, 若不存在, 则会抛出AttirbuteError异常; 若定义了default, 那么当没有属性的时候会返回默认值
  • setattr(obj,key,value): 用于修改对象的属性值, 若有key属性, 那么更新key属性, 若没有则添加key属性并赋值value
  • delattr(obj,key): 删除key属性
import uuidclass Person(object):nationality = "China"def __init__(self, name):self.name = nameself.__id = str(uuid.uuid1())def hello(self):print("Hello, I am %s, I come from %s, My ID is %s" % (self.name,self.nationality, self.__id))if __name__ == "__main__":bauer = Person("Bauer")setattr(bauer, "sex", "Man")  #设置bauer的成员属性print(getattr(bauer, "name")) #获取bauer的name属性值,输出:Bauerprint(getattr(bauer, "sex"))  #获取bauer的sex属性值,输出:Manprint(hasattr(bauer,'sex')) #判断bauer是否有名为'sex'的属性或成员,输出:Trueprint(hasattr(bauer,'hello')) #判断bauer是否有名为'hello'的属性或成员,输出:Truedelattr(bauer,'sex') #删除bauer的sex属性print(getattr(bauer, "sex")) #抛出异常:AttributeError: 'Person' object has no attribute 'sex'

深入浅出 Python 面向对象编程相关推荐

  1. 这可能是Python面向对象编程的最佳实践

    作者 | 崔庆才 来源 | 进击的Coder(ID:FightingCoder) Python 是支持面向对象的,很多情况下使用面向对象编程会使得代码更加容易扩展,并且可维护性更高,但是如果你写的多了 ...

  2. Python面向对象编程:类继承和其衍生术语

    Python面向对象编程03:类继承和其衍生术语 前面我们讲到过正则表达式字符等,上一篇分享了面向对象编程和类的结构,最后稍微提到了继承. Python面向对象编程:深度认识类class_ Pytho ...

  3. 《Python面向对象编程指南》——1.2 基类中的__init__()方法

    本节书摘来自异步社区<Python面向对象编程指南>一书中的第1章,第1.2节,作者[美]Steven F. Lott, 张心韬 兰亮 译,更多章节内容可以访问云栖社区"异步社区 ...

  4. 关于python面向对象编程中、下列说法中_关于Python面向对象编程的知识点总结

    前言 如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程. 接下来我们 ...

  5. python对象编程例子-这是我见过最详细的Python面向对象编程!建议收藏!

    原标题:这是我见过最详细的Python面向对象编程!建议收藏! 面向对象编程和函数式编程(面向过程编程)都是程序设计的方法,不过稍有区别. 面向过程编程: 1. 导入各种外部库 2. 设计各种全局变量 ...

  6. python面向对象编程的优点-Python面向对象编程——总结面向对象的优点

    Python面向对象编程--总结面向对象的优点 一.从代码级别看面向对象 1.在没有学习类这个概念时,数据与功能是分离的 def exc1(host,port,db,charset): conn=co ...

  7. python编程基础是什么-Python面向对象编程基础解析(一)

    1.什么是面向对象 面向对象(oop)是一种抽象的方法来理解这个世界,世间万物都可以抽象成一个对象,一切事物都是由对象构成的.应用在编程中,是一种开发程序的方法,它将对象作为程序的基本单元. 2.面向 ...

  8. 【Python基础】Python 面向对象编程(上篇)

    我的施工计划图 已完成专题包括: 1我的施工计划 2数字专题 3字符串专题 4列表专题 5流程控制专题 6编程风格专题 7函数使用专题 今天是面向对象编程的上篇:基础专题 Python 面向对象编程 ...

  9. Python 面向对象编程基础

    Python面向对象编程 简介:面向对象编程--Object Oriented Programming,简称 OOP,是一种程序设计思想.OOP 把对象作为程序的基本单元,一个对象包含了数据和操作数据 ...

最新文章

  1. 新站优化最应该考虑哪些方面
  2. STM32开发 -- ADC详解
  3. 带你理清 Java 混乱的日志体系 - log4j、logback、log4j2、jcl、SLFJ 究竟是啥关系?
  4. iOS UITableView 移除单元格选中时的高亮状态
  5. 三问(why?what?how?)金融领域的机器学习
  6. CentOS6.5 linux 逻辑卷管理 调整分区大小:/dev/mapper/VolGroup-lv_root 50G 47G 16M 100%
  7. 关于webapp的一点思考
  8. RS485的常用电路设计
  9. SVN客户端安装详细教程
  10. Cesium开发: Draco模型压缩
  11. 如何创建表以及设计表需要注意什么,oracle五种限制
  12. 微信又支持改微信号了
  13. Python 安装 包时 VC 14 找不到错误终极解决办法
  14. Reac16+Monaco打造代码编辑器(前端部分)
  15. 计算机硬件 OR CX 1,计算机硬件复习提纲
  16. 控制器模式_前控制器模式简介,第1部分
  17. C语言:运算符-符号常量-输入输出
  18. Git快速入门-git stash 暂存变更,git reset 撤销commit,git revert 回退远程版本库
  19. Linux PCI网卡驱动的详细分析
  20. 广东大学生计算机设计大赛,我校学子在广东省大学生计算机设计大赛中荣获一等奖...

热门文章

  1. 基础会计学习笔记 6.借贷记账法 7.会计分录
  2. linux tf 卡驱动理解
  3. 生成扩散模型漫谈:最优扩散方差估计(上)
  4. 3d室内导航系统-停车导航-人员位置感知技术
  5. Android设置颜色
  6. Unable to handle kernel paging request at virtual address 的解决办法
  7. slam十四讲之第六讲带你看懂g2o
  8. 同等训练时间的前提下,使用杠铃真的比哑铃更高效吗?
  9. 2022中国广告论坛圆满落幕,虚拟数字人+虚拟场景直播打造虚拟论坛
  10. 明天要去阿里巴巴上班了,有点激动哦