python3 类_Python3面向对象-类与实例

本文深入介绍了Python的面向对象特性,包括封装、继承和多态。通过实例详细阐述了类的定义、实例化、属性与方法的使用,以及静态方法和类方法的区别。此外,还探讨了Python中的属性访问、方法调用以及属性的public和private概念,以及如何使用property装饰器实现属性的封装。最后,通过示例展示了静态方法和类方法在统计类实例数量场景的应用。
摘要由CSDN通过智能技术生成

在Python中一切都是对象,Python从设计之初就已经是一门面向对象的语言。

面向对象的三个特征:

1:封装:把具有相同属性和功能的内容封装在一个对象中。

2:继承:子类可以自动拥有父类中除了私有属性外的其他所有内容。

3:多态:同一个对象,可以拥有多种形态,python原生自带多态性。

下面系列文章将从这三个特征中展开介绍Python中的面向对象。

1:Python中类的定义:

其形式如下:

class name(superclass,...):   # 与def 一样 Class是一种隐含的赋值运算    attr = value       # 类属性    def method(...):   # 类方法   (无self参数)        pass     # 类方法    @classmethod    def clsMethod(cls):  # cls表示的类        print(cls)        obj = cls()  # 可以动态的创建对象        print('类方法')      def method(self,...):  # 实例方法  (有self参数)        self.attr = value  # 实例属性

Python中的Class语句并不是声明式的,与def一样,Class语句是对象的创建者,并且是一种隐含的赋值运算。与def语句一样,Class语句也是真正的可执行代码,也就是说在执行Class语句之前,所定义的类是不存在的。当执行到Class语句时,就会创建一个变量名为name的对象(也就是类名),这个对象具有自己的属性和方法(类属性,类方法),同时这个对象通过某种调用能够创造其他对象(也就是实例)。

在Class语句内,任何的赋值语句都会产生类属性。任何通过"类名.属性"赋值的语句也会产生类属性。

要点:

a:Class语句不是声明,是隐含的赋值,类名就是变量名。

b:在Class语句内有类方法,类属性,实例方法(这些属于类名命名空间下的属性),实例属性(此属性不属于类名命名空间下);类方法,类属性被类实例所共享。

c:在Class语句内,任何的赋值语句都会产生类属性。以 类名.属性 = xx 形式的赋值也会产生类属性。

d:在Python中,类中的所有属性和方法都是public的(包括_,__开头的属性都是Public的,可以看作是伪私有),同时类中的所有方法都是virtual的。

2:Python中类的实例:

类就是实例工厂,它可以创建其他的多个实例,类属性和类方法存在于类中,可以被多个实例共享。

在Class语句内的实例方法中通过self.属性 = xxx 方式赋值的属性都属于类的实例,多个实例都会有独立的。

实例1.属性1 = xx 形式的赋值只会给实例1添加属性,与其他实例没有关系

示例代码:

# encoding=gbk class Person:    #  隐含的赋值(是通过元类来赋值的),Person 就是一个变量名,可以通过 person_1 = Person('德华',45) 的方式创建一个对象    country  = '中国'    # 静态方法    @staticmethod    def printCountry():        print(Person.country)     # 类方法,    @classmethod    def clsMethod(cls):  # cls表示的类        print(cls)        obj = cls()  # 可以动态的创建对象        print('类方法')       def __init__(self,name,age):  #  Person类的构造函数,用于创建实例对象,        self.name = name  # 实例的属性        self.age = age     def setBirthday(self,birthday):        self.birthday = birthday     def PrintBirthday(self):        print('self.birthday=', self.birthday)     def printName(self):        print('self.name=',self.name) # __dict__ 查看对象中的属性print(Person.__dict__)person_1 = Person('德华',18)person_2 = Person('德纲',19)print(person_1.__dict__)  # {'name': '德华', 'age': 18}print(person_2.__dict__)  # {'name': '德纲', 'age': 19}print(Person.__dict__)    # 输出与第一的一样; 上面的实例化对象,不会对类Person产生影响 print('---01--:'+'*'*60)# 1:添加属性,即赋值操作,给谁赋值就在谁的命名空间中添加属性。(赋值操作不会发生继承搜索)Person.A1 = 'test_a1'person_1.A2 = 'test_a2'person_2.A3 = 'test_a3' Person.B1 = 'test_B1_Person'person_1.B1 = 'test_B1_Person1'person_2.B1 = 'test_B1_Person2' person_1.setBirthday('1990-10')print(person_1.__dict__)  # {'name': '德华', 'age': 18, 'A2': 'test_a2', 'B1': 'test_B1_Person1', 'birthday': '1990-10'}print(person_2.__dict__)  # {'name': '德纲', 'age': 19, 'A3': 'test_a3', 'B1': 'test_B1_Person2'}    person_2没有调用setBirthday,故不会有birthday属性print(Person.__dict__)    # 比上次多了  'A1': 'test_a1', 'B1': 'test_B1_Person' print('---02--:'+'*'*60)# 2:访问属性,即属性引用(属性引用会发生继承搜索):首先在自己的命名空间中找,找不到就去创建它的类中找,也找不到就去创建它的类的父类中找,如最后都没有找到,就抛出异常。print(Person.A1)  #  输出test_a1print(person_1.A1) # 输出test_a1,person_1命名空间是没有A1的,自己没有会去类名的命名空间中找print(person_2.A1) # 输出test_a1  person_2命名空间也是没有A1的,自己没有会去类名的命名空间中找 print(Person.B1)  #  输出 test_B1_Personprint(person_1.B1) # 输出 test_B1_Person1,person_1命名空间中有B1print(person_2.B1) # 输出 test_B1_Person2,person_2命名空间中有B1 print('---03--:'+'*'*60)# 3:方法调用# 类方法:只能是通过类名来调用Person.printCountry()# person_1.printCountry()  # 这样会报错# person_2.printCountry()  # 这样会报错 # 实例方法:通过实例调用,或者通过类名+传递实例参数调用person_1.printName()person_2.printName()# Person.printName()  # 不能这样直接调用,需要传递一个实例参数,如下:Person.printName(person_1)  # 这里与 person_1.printName() 调用是等价的Person.printName(person_2) print('---03--:'+'*'*60)# 4:添加方法,同添加属性,给谁添加方法就在谁的命名空间中添加方法。(赋值操作不会发生继承搜索)# 给实例添加方法,被添加方法的实例中才有def add(a,b):    return a+bperson_2.add = add  #print(person_2.add(10,19)) print(person_1.__dict__)  # {'name': '德华', 'age': 18, 'A2': 'test_a2', 'B1': 'test_B1_Person1', 'birthday': '1990-10'}print(person_2.__dict__)  # {'name': '德纲', 'age': 19, 'A3': 'test_a3', 'B1': 'test_B1_Person2', 'add': }print(Person.__dict__)    # 结果中不会有 add方法 # Person.add(person_2,10,18)  不能这样调用,add只在person_2中才有 # 给类添加实例方法,所有实例都会共享 # def add(a,b):#     return a+b# Person.add = add  # 这样赋值会导致下面的定义出错# print(person_1.add(10,19)) # 需要添加一个实例对象作为参数。def add2(aaa,a,b):    print(aaa)  #  aaa 就是Person的一个实例    return a+bPerson.add2 = add2  # 这样赋值会导致下面的定义出错print(person_1.add2(100,19))# 也可以通过下面方式调用,因为add2是类Person命名空间中的实例方法print(Person.add2(person_1,200,30)) 

3:Python3中的伪私有属性:

在Python3中,类中的所有属性都是公有的,即public的。但是在Python3中提供了以双下划线(__)开头的属性,表现为伪私有。

代码如下:(后面会介绍怎么实现这种伪私有)

# encoding=gbk class Person:    def __init__(self,name,age):        # 以双下划线(__)开头的实例属性,在创建实例的时候,会把属性名修改为:_类名_属性(此处为_Person__name),        # 所以 以 实例.__name 访问属性 自然是不能访问的,其效果就是属性__name表现为私有一样,        # 你依然可以通过 实例._Person__name 来访问这个属性        self.__name = name        self._age = age print(Person.__dict__)   p = Person('ixusy88',18)print(p.__dict__)  # {'_Person__name': 'ixusy88', '_age': 18}# print(p.__name)  # AttributeError: 'Person' object has no attribute '__name'  , 没有__name这个属性print(p._Person__name)  # 可以访问  输出 ixusy88print(p.__dict__['_Person__name']) # 可以访问  输出 ixusy88

4:property属性:

4.1 内置函数property

attribute = property(fget,fset,fdel,doc)

代码:

# encoding=gbk class Person:    def __init__(self,name):        self._name = name     def getName(self):        print('get')        return self._name     def setName(self, value):        print('set',value)        self._name = value     def delName(self):        print('del',self._name)        del self._name     name = property(getName,setName,delName,'name property') p = Person('ixusy88')print('1:' + '*'*20)print(p.name)print('2:' + '*'*20)p.name = '100'print(p.name)print('3:' + '*'*20)del p.name

4.2 setter和dleter装饰器

# encoding=gbkclass Person:    def __init__(self,name):        self._name = name    @property    def name(self):        print('get')        return self._name     @name.setter    def name(self, value):        print('set',value)        self._name = value     @name.deleter    def name(self):        print('del',self._name)        del self._name p = Person('ixusy88')print('1:' + '*'*20)print(p.name)print('2:' + '*'*20)p.name = '100'print(p.name)print('3:' + '*'*20)del p.name

5:静态方法和类方法:

类中有如下方法:

实例方法:传入一个self实例对象 (默认方式)

静态方法:不传入额外的对象 (通过staticmethod)

类方法:传入一个类对象 (通过classmethod)

5.1:静态方法

示例:统计实例的数量:

# encoding=gbk # 静态方法,统计实例的数量class Test:    InstancesNums = 0    def __init__(self):        Test.InstancesNums = Test.InstancesNums + 1     @staticmethod    def printInstancesNums():        print(f'InstancesNums is {Test.InstancesNums}') class Sub(Test):    pass t = Test()t = Test()t = Test()s = Sub()Test.printInstancesNums()t.printInstancesNums()s.printInstancesNums()

5.2:类方法

统计类实例数量:

# encoding=gbk # 静态方法,统计实例的数量class Test:    InstancesNums = 0    def __init__(self):        Test.InstancesNums = Test.InstancesNums + 1     @classmethod    def printInstancesNums(cls):        print(f'InstancesNums is {cls.InstancesNums}') class Sub(Test):    @classmethod    def printInstancesNums(cls):        print(f'InstancesNums is {cls.InstancesNums}') class Other(Test):    pass t = Test()t = Test()o = Other()s = Sub()Test.printInstancesNums()t.printInstancesNums()Sub.printInstancesNums()Other.printInstancesNums()

统计每个类实例数量:

# encoding=gbk # 静态方法,统计实例的数量class Test:    InstancesNums = 0    def __init__(self):        self.count()     @classmethod    def count(cls):        cls.InstancesNums += 1     @classmethod    def printInstancesNums(cls):        print(f'InstancesNums is {cls.InstancesNums}') class Sub(Test):    InstancesNums = 0     def __init__(self):        super().__init__()     @classmethod    def printInstancesNums(cls):        print(f'InstancesNums is {cls.InstancesNums}') class Other(Test):    InstancesNums = 0    pass  t = Test()o = Other()o = Other() s = Sub()s = Sub()s = Sub() Test.printInstancesNums()Other.printInstancesNums()Sub.printInstancesNums()
894723ca1bc4d61b5ed658e67675f060.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值