Python3中类的高级语法及实战



Python3中类的高级语法及实战

Python3(基础|高级)语法实战(|多线程|多进程|线程池|进程池技术)|多线程安全问题解决方案

Python3数据科学包系列(一):数据分析实战

Python3数据科学包系列(二):数据分析实战



一:  类定义语法 

通过下面的实例,你将会了解到如下的内容体系:

(1)类静态属性: 定义类时定义的属性

(2)类动态属性: 实例化类后,通过:对象.属性= 属性值 添加的属性

(3)类初始化过程: __init__(self)被执行,相当于java中的构造函数

(4)类变量与实例变量: 类变量所属所有的实例对象;实例对象只属于本实例

(5)怎样限制某个类无限添加动态属性:使用__slots__ 内置的元组限定动态添加的属性

(6)类的成员访问权限: private 与public 两种权限

(7)装饰器:让get|set方法装饰成属性,可以使用:对象.属性或者对象.属性=属性值的方式操作私有属性

(8)Python类的三种注释

# -*- coding:utf8 -*-
class ClassCreate:
    """A simple example class"""
    # 类的静态属性i
    i = 1234

    @staticmethod
    def functionMethod(self):
        return "I Love You !"


print(
    """
    【面向对象OOP编程是一种编程思想:
    Python中使用关键字class来创建一个类,class之后紧根类名,并与冒号结尾】
    """)

print("调用类的静态方法:", "使用类名.静态方法(类的实例化对象)")

myClass = ClassCreate()
print(ClassCreate.functionMethod(myClass))
print()
print("类的成员变量为所有对象实例共享:[静态属性] ", myClass.i)

print(
    """
    调用类的内置属性: __name__,__doc__,__module__,__base__,__dict__
    """
)
print("打印类的内置属性: ")
print(ClassCreate.__class__)
print(ClassCreate.__name__)
print(ClassCreate.__doc__)
print(ClassCreate.__base__)
print(ClassCreate.__bases__)
dictData = ClassCreate.__dict__
print(dictData)
print()
print(dictData['functionMethod'])

print("""
     类的属性分: 
        (1)定义类时定义的属性叫静态属性
        (2)动态属性是通过:类对象.属性名=属性值的方式动态添加的属性成为动态属性
""")


class Person:
    pass


person = Person()
person.name = "张三"
person.age = 30
print('''
    使用一个空类,处理动态添加属性的问题,在实际引用中,所有的类都具有这种动态添加的属性的特性
''')
print("访问类的动态属性: 用户的名称%s" % person.name, "用户的年龄: %d" % person.age)

print("删除类的动态属性: name: 使用: ", "del person.name")
del person.name

try:
    print("访问类的动态属性: 用户的名称%s" % person.name, "用户的年龄: %d" % person.age)
except AttributeError as err:
    print("访问删除的动态属性name,异常: ", err.__traceback__)

print("""
   为了无上限的给类动态添加属性: 可以使用__slots__属性给类可以动态添加属性的限制,__slots__元组可以限制类中添加的属性:例如定义类的时候
   限制类只能添加动态属性: __slots__ = ('name','age','address')这些属性,如添加这些以外的属性,将会报错
""")

print('例如: 我们定义Record类')


# 定义一个空类,设置合法的属性为
class Record:
    """使用内置属性__slots__声明类的合法动态属性"""
    __slots__ = ('name', 'age')
    address = ''  # 该类包括一个类属性: address


Anna = Record()
Anna.name = '张三'
# 修改类变量address,只能使用:类名.属性名 = 属性值;而不能使用:对象.属性名=属性值的方式
Record.address = '北京市'
Anna.age = 20

print("Anna : ", Record.__dict__)
# 访问类变量确可以使用:对象名.属性名
print("长期居住地址: ", Record.address)

print('''
   当我们动态前景: college属性时,看看发生声明效果
''')
try:
    Anna.college = '清华大学'
    print(Anna.college)
except AttributeError as err:
    print("添加非法的动态属性(college),异常信息: %s......." % err)

print()
print('-------------------------------------------------------------------------------------------------')

print("""
    实例化对象: 通常我们要使用类中的成员及方法完成相应的业务逻辑,需要实例化该类: python中,实例化对象有两种方式:
    (1)类名+括号:  类名()
         当我们没有在类中声明__init__()方法或者时声明了__init(self)__时,实例化类就只需: 类名() 即可
    (2)类名+括号(参数列表)
         当我们声明了__init__(self,other parameters) ,方式除了有self参数外,还有我们拓展的对象成员变量时,需要使用这种方式创建类实例对象
""")


class PersonInstance:
    """类实例化的方式,重写类的init方法"""

    # 该方法在类实例化时,首先被调用,主要完成一些初始化功能
    def __init__(self, name, age, address):
        self.name = name
        self.address = address
        self.age = age
        print("name|age|address这上属性属于该类实例化后的对象的成员;这些成员变量属于所有实例对象共有")

    def getinfo(self):
        return self.name, str(self.age), self.address


person = PersonInstance("老杨", 20, "北京市海淀区中关村软件创新中心101")
print("调用类的普通方法,看法该方法返回的值 ", person.getinfo())
print("调用类的普通方法,看法该方法返回的值类型: ", type(person.getinfo()))

print()
print("隐藏调用类的初始化方法: ")


class MyChildren:
    """演示隐藏调用类的初始化化法"""

    def __init__(self):
        print("""
        MyChildren类初始化时,init方法会被调用;对于一个没有初始化函数的类,在实例化时,
        也会调用内部默认的__init__函数,如果在类中实现了函数__init__,就会优先调用自定义的函数__init__
        """)


# 类初始化对象
myChildren = MyChildren()
print("显示调用: __init__()初始化方法:")
print("显示调用的结果: ", MyChildren.__init__)
print("""
    注意:如果类中的__init__()函数,有除了self以外的参数。实例化类时,就必须输入与__init__函数
    对应的参数,否则就会报错...;
    在类的代码块中,可以使用self关键字来指定本身。另外,类中的成员函数必须第一个参数时self,这样才能保证,
    使用类实例化的对象能够调用自己的成员函数;
""")

print('--------------------将成员函数定义在类外面-----------------------------')

print("""
   如果将类中的方法看成函数的话,完全可以把方法定义在类的外边,但是函数的第一个参数必须时self这个规则必须保留
""")


# 定义在类外面的方法
# 这种方法是的成员函数可以被多个类使用,从而提高了代码的重用性
def handlerFun(self):
    return "I Love You!....."


class MyHandlerFun:
    """A simple example class....."""
    idea = 123456
    # 在类的内部指定成员函数
    fun = handlerFun  # 函数本身就是一个对象,可以赋值给变量


myHandlerFun = MyHandlerFun()
print("调用实例化对象的成员函数handlerFun: ", myHandlerFun.fun())
print("调用实例化对象的成员函数handlerFun: ", MyHandlerFun.fun(myHandlerFun))

print('-------------------------------------类内的成员互访------------------------------------')


class MyInnerClass:
    """A Record class"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def getAge(self):
        return self.age

    def getName(self):
        return self.name

    def getRecord(self):
        return self.name, self.age


print("""
   在类内部可以使用self.属性或者self.方法 ;  self代表当前类的实例对象;
""")

myInnerClass = MyInnerClass("老高", 25)
print("MyInnerClass实例化对象信息: ", myInnerClass.__dict__)
print(myInnerClass.getRecord())
print("getRecord方法返回值类型:", type(myInnerClass.getRecord()))

print()

print("""
    Python中的访问权有: public(共有的)|private(私有的)
    属性访问权限体现为: 在变量前加两个下划线"__",表示私有的,没加默认为公有的访问权限
    也就是说Python中默认权限时public,即所有的对象都是可以访问的
""")

二:静态|动态属性演示

D:\program_file_worker\anaconda\python.exe D:\program_file_worker\python_source_work\SSO\grammar\oop\ClassGrammarCreate.py 

    【面向对象OOP编程是一种编程思想:
    Python中使用关键字class来创建一个类,class之后紧根类名,并与冒号结尾】
    
调用类的静态方法: 使用类名.静态方法(类的实例化对象)
I Love You !

类的成员变量为所有对象实例共享:[静态属性]  1234

    调用类的内置属性: __name__,__doc__,__module__,__base__,__dict__
    
打印类的内置属性: 
<class 'type'>
ClassCreate
A simple example class
<class 'object'>
(<class 'object'>,)
{'__module__': '__main__', '__doc__': 'A simple example class', 'i': 1234, 'functionMethod': <staticmethod(<function ClassCreate.functionMethod at 0x0000015B35B64D60>)>, '__dict__': <attribute '__dict__' of 'ClassCreate' objects>, '__weakref__': <attribute '__weakref__' of 'ClassCreate' objects>}

<staticmethod(<function ClassCreate.functionMethod at 0x0000015B35B64D60>)>

     类的属性分: 
        (1)定义类时定义的属性叫静态属性
        (2)动态属性是通过:类对象.属性名=属性值的方式动态添加的属性成为动态属性


    使用一个空类,处理动态添加属性的问题,在实际引用中,所有的类都具有这种动态添加的属性的特性

访问类的动态属性: 用户的名称张三 用户的年龄: 30
删除类的动态属性: name: 使用:  del person.name
访问删除的动态属性name,异常:  <traceback object at 0x0000015B35B7CD80>

   为了无上限的给类动态添加属性: 可以使用__slots__属性给类可以动态添加属性的限制,__slots__元组可以限制类中添加的属性:例如定义类的时候
   限制类只能添加动态属性: __slots__ = ('name','age','address')这些属性,如添加这些以外的属性,将会报错

例如: 我们定义Record类
Anna :  {'__module__': '__main__', '__doc__': '使用内置属性__slots__声明类的合法动态属性', '__slots__': ('name', 'age'), 'address': '北京市', 'age': <member 'age' of 'Record' objects>, 'name': <member 'name' of 'Record' objects>}
长期居住地址:  北京市

   当我们动态前景: college属性时,看看发生声明效果

添加非法的动态属性(college),异常信息: 'Record' object has no attribute 'college'.......

-------------------------------------------------------------------------------------------------

    实例化对象: 通常我们要使用类中的成员及方法完成相应的业务逻辑,需要实例化该类: python中,实例化对象有两种方式:
    (1)类名+括号:  类名()
         当我们没有在类中声明__init__()方法或者时声明了__init(self)__时,实例化类就只需: 类名() 即可
    (2)类名+括号(参数列表)
         当我们声明了__init__(self,other parameters) ,方式除了有self参数外,还有我们拓展的对象成员变量时,需要使用这种方式创建类实例对象

name|age|address这上属性属于该类实例化后的对象的成员;这些成员变量属于所有实例对象共有
调用类的普通方法,看法该方法返回的值  ('老杨', '20', '北京市海淀区中关村软件创新中心101')
调用类的普通方法,看法该方法返回的值类型:  <class 'tuple'>

隐藏调用类的初始化方法: 

        MyChildren类初始化时,init方法会被调用;对于一个没有初始化函数的类,在实例化时,
        也会调用内部默认的__init__函数,如果在类中实现了函数__init__,就会优先调用自定义的函数__init__
        
显示调用: __init__()初始化方法:
显示调用的结果:  <function MyChildren.__init__ at 0x0000015B35B65120>

    注意:如果类中的__init__()函数,有除了self以外的参数。实例化类时,就必须输入与__init__函数
    对应的参数,否则就会报错...;
    在类的代码块中,可以使用self关键字来指定本身。另外,类中的成员函数必须第一个参数时self,这样才能保证,
    使用类实例化的对象能够调用自己的成员函数;

--------------------将成员函数定义在类外面-----------------------------

   如果将类中的方法看成函数的话,完全可以把方法定义在类的外边,但是函数的第一个参数必须时self这个规则必须保留

调用实例化对象的成员函数handlerFun:  I Love You!.....
调用实例化对象的成员函数handlerFun:  I Love You!.....
-------------------------------------类内的成员互访------------------------------------

   在类内部可以使用self.属性或者self.方法 ;  self代表当前类的实例对象;

MyInnerClass实例化对象信息:  {'name': '老高', 'age': 25}
('老高', 25)
getRecord方法返回值类型: <class 'tuple'>


    Python中的访问权有: public(共有的)|private(私有的)
    属性访问权限体现为: 在变量前加两个下划线"__",表示私有的,没加默认为公有的访问权限
    也就是说Python中默认权限时public,即所有的对象都是可以访问的


Process finished with exit code 0
 

三:通过get或者set方法获取或者修改私有属性

通常,在类中定义的私有成员,通常需要提供两个方法:
get(self)方法,读取私有属性
set(self ,value)方法, 修改私有属性
另外,我们也可以使用装饰器操作,实现访问私有属性的get方法装饰为公有的属性一样,可以使用:对象.属性  这样的方式访问私有成员;
下面我们来提供: set方法的装饰器,可以通过: 对象.私有属性= 属性值  的方式修改私有变量的值 ;
也即是使用装饰器技术实现类的私有化(@property)
我们知道,私有化技术提供了程序的健壮性,使得一些不愿意暴露的信息细节封装在类中,这些信息不暴露给调用方,这对应一些机密信息得到基本的安全保障
但是,必须提供一个为私有化变量封装的get方法,通过调用get方法对外提供服务
由于私有化属性不能被直接访问,使得类属性的取值方式发生了改变:也即是不能使用:【 实例对象.属性 】的方式进行访问
下面我们通过"装饰器"技术,它可以将get和set方法装饰成类中的一个属性,从而是私有化的类属性也可以直接方法

# -*- coding:utf8 -*-


# 继承:inherit
class MyClassInheritBaseClass:
    """A simaple inherit class"""
    # 职业: 默认科学家,是有变量
    __Occupation = "scientist"

    # 重写__init__(self)
    def __init__(self, name, age, address, college):
        self.name = name
        self.age = age
        self.address = address
        self.college = college

    # 获取类的成员属性
    def getMyClassInheritBaseClass(self):
        return self.name, self.age, self.address, self.college

    # 提供公共方法方位类中的私有成员属性
    def getOccupation(self):
        return self.__Occupation

    # 将get函数装饰成属性
    @property
    def Occupation(self):
        return self.__Occupation

    def setOccupation(self, value):
        self.__Occupation = value


print()
my = MyClassInheritBaseClass('老杨', 30, '北京市朝阳区三里屯大街1001号胡同20小院', '北京大学')
# 通过set方法修改私有变量
my.setOccupation("艺术家")
print("调用公共方法访问私有属性: ", my.getOccupation())
print("================================================================================================")
my1 = MyClassInheritBaseClass('老高', 30, '北京市昌平区001号胡同20小院', '北京大学')
print("调用公共方法访问私有属性my1: ", my.getOccupation())
print("==================================my1==============================================================")
print("通过访问属性的方式访问私有属性,该私有属性时通过装饰器转换get方法为可以访问的公有属性: %s" % my.Occupation)
print()
print("类中的属性字典: ", MyClassInheritBaseClass.__dict__)
print("""
  Python语法会自动私有变量改名字,通过这种方式,让实例化对象找不动私有变量,下面我们直接访问这个名称来验证结果
""")
print("私有属性访问: ", my._MyClassInheritBaseClass__Occupation)

print("""
   通常,在类中定义的私有成员,通常需要提供两个方法:
   get(self)方法,读取私有属性
   set(self ,value)方法, 修改私有属性
   另外,我们也可以使用装饰器操作,实现访问私有属性的get方法装饰为公有的属性一样,可以使用:对象.属性  这样的方式访问私有成员,如上面的:
   ===================== @property=装饰器==============================
    @property
    def Occupation(self):
        return self.__Occupation
    ==============================================================
        
""")

输出效果如下:


D:\program_file_worker\anaconda\python.exe D:\program_file_worker\python_source_work\SSO\grammar\oop\ClassGrammarInheritBaseCreateClass.py 

调用公共方法访问私有属性:  艺术家
================================================================================================
调用公共方法访问私有属性my1:  艺术家
==================================my1==============================================================
通过访问属性的方式访问私有属性,该私有属性时通过装饰器转换get方法为可以访问的公有属性: 艺术家

类中的属性字典:  {'__module__': '__main__', '__doc__': 'A simaple inherit class', '_MyClassInheritBaseClass__Occupation': 'scientist', '__init__': <function MyClassInheritBaseClass.__init__ at 0x000002BFB8454F40>, 'getMyClassInheritBaseClass': <function MyClassInheritBaseClass.getMyClassInheritBaseClass at 0x000002BFB8454FE0>, 'getOccupation': <function MyClassInheritBaseClass.getOccupation at 0x000002BFB8455080>, 'Occupation': <property object at 0x000002BFB843D210>, 'setOccupation': <function MyClassInheritBaseClass.setOccupation at 0x000002BFB84551C0>, '__dict__': <attribute '__dict__' of 'MyClassInheritBaseClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClassInheritBaseClass' objects>}

  Python语法会自动私有变量改名字,通过这种方式,让实例化对象找不动私有变量,下面我们直接访问这个名称来验证结果

私有属性访问:  艺术家

   通常,在类中定义的私有成员,通常需要提供两个方法:
   get(self)方法,读取私有属性
   set(self ,value)方法, 修改私有属性
   另外,我们也可以使用装饰器操作,实现访问私有属性的get方法装饰为公有的属性一样,可以使用:对象.属性  这样的方式访问私有成员,如上面的:

Process finished with exit code 0

-------------------------------------从输出结果----------------------------------------------------------------

我们可以看到,修改类的私有属性时,一个类实例化对象修改,会影响到其它实例化对象的改私有属性的值也会受到影响;这点我们需要特别注意;一处修改多处受到影响; 下面的装饰器可以来修改私有属性时,可以在对应修改属性的方法中添加判断逻辑进行限制,以便满足业务需求;
 

四: 通过装饰器来获取私有属性或者修改私有属性

通过"装饰器" 来实现类私有化属性的get方法与set方法装饰成类的属性, 被装饰后的私有属性可以与原属性同名,也可以不同同名; 通过装饰器装饰后的set或者get方法后,访问私有属性可以使用: 对象.属性的名称 的方式来访问私有属性;  装饰后的属性与被装饰的方法的名称相同;

print("Python语法中的装饰器:")

print()
print("""
   下面我们来提供: set方法的装饰器,可以通过: 对象.私有属性= 属性值  的方式修改私有变量的值 ;
   也即是使用装饰器技术实现类的私有化(@property)
   我们知道,私有化技术提供了程序的健壮性,使得一些不愿意暴露的信息细节封装在类中,这些信息不暴露给调用方,这对应一些机密信息得到基本的安全保障
   但是,必须提供一个为私有化变量封装的get方法,通过调用get方法对外提供服务
   由于私有化属性不能被直接访问,使得类属性的取值方式发生了改变:也即是不能使用:【 实例对象.属性 】的方式进行访问
   下面我们通过"装饰器"技术,它可以将get和set方法装饰成类中的一个属性,从而是私有化的类属性也可以直接方法
""")

print()
print("------------------------装饰器@property实现私有变量的get函数------------------------------")


class ExchangeMeetingClassGet:
    """使用装饰器(@property)将访问类私有属性的get方法装饰成类的一个属性,使得可以改私有属性可以直接访问"""
    __Operation = "世界文化交流"
    __address = '北京市海淀区中关村文化交流中心北苑路北10002路'

    # 重写类的__init__方法,该方法相当于java中的有参构造函数;该函数会在类实例化时被python内部机制调用
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 定义一个成员函数(获取当参会人员基本信息)
    def getExchangeMeetingClass(self):
        return self.name, self.age

    # 将get方法装饰成属性
    @property
    def Address(self):
        return self.__address


# 实例化对象exchangeMeeting
exchangeMeeting = ExchangeMeetingClassGet("张三", 30)
# 访问私有属性__Operation|__address
# 访问__Operation属性时,会抛出异常: 'ExchangeMeetingClass' object has no attribute '__Operation'
try:
    print("私有属性【__Operation】:", exchangeMeeting.__Operation)
except AttributeError as err:
    print("访问类的私有属性'__Operation'异常,异常信息:  ", err)

print()
print("访问类的私有属性[__address]: ", exchangeMeeting.Address)
'''
  访问类的私有属性时【__address】:
  我们需要注意: (1)可以使使用实例对象.属性名  的方式访问类的私有属性,但是该属性名称必须与装饰器装饰的方法名保持一致,而不是一私有属性名保持一致
  如我们这样访问私有成员会报错: 
  print("访问类的私有属性[__address]: ", exchangeMeeting.__address)
'''

print()
print("-----------下面我们来探究通过装饰器来使得私有化属性可以被修改-----------------------")


class ExchangeMeetingClassSet:
    """使用装饰器(@property)将访问类私有属性的get方法装饰成类的一个属性,使得可以改私有属性可以直接访问"""
    __Operation = "世界文化交流"
    __address = '北京市海淀区中关村文化交流中心北苑路北10002路'

    # 重写类的__init__方法,该方法相当于java中的有参构造函数;该函数会在类实例化时被python内部机制调用
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 定义一个成员函数(获取当参会人员基本信息)
    def getExchangeMeetingClass(self):
        return self.name, self.age

    # 将get方法装饰成属性
    @property
    def Address(self):
        return self.__address

    @property
    def OperationSetValue(self):
        return self.__Operation

    # 将set函数装饰成属性,通过该装饰器,可以使修改私有属性: 实例对象.私有属性 = 属性值
    # 该set装饰器必须与上面的get装饰器同时存在,不然程序识别不了该装饰器;而且get与set的方法名必须相同,其实,私有属性__Operation已经被改名为OperationSetValue
    @OperationSetValue.setter
    def OperationSetValue(self, value):
        if (value != "世界文化交流") and (value != "世界艺术交流展会"):
            raise (ValueError('Operation must be 世界文化交流 or 世界艺术交流展会'))
        else:
            self.__Operation = value


exchangeMeetingClassSet = ExchangeMeetingClassSet("小张", 50)
# 修改私有属性值{__Operation:'世界艺术交流展会'}
exchangeMeetingClassSet.OperationSetValue = '世界艺术交流展会'
print("实例对象属性集合: ", exchangeMeetingClassSet.__dict__)
print("访问类私有属性[__Operation]: ", exchangeMeetingClassSet.OperationSetValue)

五:装饰器装饰set|get方法后,访问私有属性运行效果


Python语法中的装饰器:


   下面我们来提供: set方法的装饰器,可以通过: 对象.私有属性= 属性值  的方式修改私有变量的值 ;
   也即是使用装饰器技术实现类的私有化(@property)
   我们知道,私有化技术提供了程序的健壮性,使得一些不愿意暴露的信息细节封装在类中,这些信息不暴露给调用方,这对应一些机密信息得到基本的安全保障
   但是,必须提供一个为私有化变量封装的get方法,通过调用get方法对外提供服务
   由于私有化属性不能被直接访问,使得类属性的取值方式发生了改变:也即是不能使用:【 实例对象.属性 】的方式进行访问
   下面我们通过"装饰器"技术,它可以将get和set方法装饰成类中的一个属性,从而是私有化的类属性也可以直接方法


------------------------装饰器@property实现私有变量的get函数------------------------------
访问类的私有属性'__Operation'异常,异常信息:   'ExchangeMeetingClassGet' object has no attribute '__Operation'

访问类的私有属性[__address]:  北京市海淀区中关村文化交流中心北苑路北10002路

-----------下面我们来探究通过装饰器来使得私有化属性可以被修改-----------------------
实例对象属性集合:  {'name': '小张', 'age': 50, '_ExchangeMeetingClassSet__Operation': '世界艺术交流展会'}
访问类私有属性[__Operation]:  世界艺术交流展会
 

六: Python中父子类面向对象编程思想

在Python中,父类可以派生出多个子类,也就是一个父类可以被多个子类继承;子类可以继承父类的属性和方法
不像java,只允许一个类继承单个类,不允许同时继承多个类;但是Python中运行一个类继承多个类;
即子类可以继承父类的所有的属性及方法:
   通过父子类的编程思想来设计架构,这是面向对象的思想。对应全部都遵守的共性,用父类来描述:对于满足部分共性的对象,用多个子类来描述
   继承的语法:
   class + 类名(父类的类名1,父类的类名1,.....父类的类名n):
      语句块1
      语句块2
      语句块3
         .
         .
         .
      语句块n,
   当括号内的父类名称是单个的时候,就是单继承否则就是多继承

(1)学习java的小伙伴知道,覆盖是指子类重写父类的方法,重写发生在子类与父类之间,当父类的方法实现的业务不能满足我们需要的时候,此时我们可以通过重写
父类的方法来实现我们的业务逻辑;通过拓展父类的方法,可以在不改变父类的前提下,不会影响其他继承同一父类的类产生影响;
当子类的方法与父类的方法同名时且参数表列相同时,父类的方法也将失效; 通常子类覆写父类方法的同时,需要调用下父类的被覆写的方法;
这种情况下,可以通过以下的方式调用父类方法:
FatherClassName.method(self,arguments)
(2)Python中采用了C3线性化算法去检索父类,保证每个父类只检索一次,以避免检索过程陷入死循环

# -*- coding:utf8 -*-

print("类的认知:")
print("Python中类的继承关系: 派生与继承时针对子类与父类而言")

'''
  在Python中,父类可以派生出多个子类,也就是一个父类可以被多个子类继承;子类可以继承父类的属性和方法
  不像java,只允许一个类继承单个类,不允许同时继承多个类;但是Python中运行一个类继承多个类;
  即子类可以继承父类的所有的属性及方法:
     通过父子类的编程思想来设计架构,这是面向对象的思想。对应全部都遵守的共性,用父类来描述:对于满足部分共性的对象,用多个子类来描述
     继承的语法:
     class + 类名(父类的类名1,父类的类名1,.....父类的类名n):
        语句块1
        语句块2
        语句块3
           .
           .
           .
        语句块n,
     当括号内的父类名称是单个的时候,就是单继承否则就是多继承
'''
print('-----------------------------------认知升维----------------------------------------')
print("-----------------------------------来认识覆盖|重写----------------------------------")
print("""
    (1)学习java的小伙伴知道,覆盖是指子类重写父类的方法,重写发生在子类与父类之间,当父类的方法实现的业务不能满足我们需要的时候,此时我们可以通过重写
    父类的方法来实现我们的业务逻辑;通过拓展父类的方法,可以在不改变父类的前提下,不会影响其他继承同一父类的类产生影响;
    当子类的方法与父类的方法同名时且参数表列相同时,父类的方法也将失效; 通常子类覆写父类方法的同时,需要调用下父类的被覆写的方法;
    这种情况下,可以通过以下的方式调用父类方法:
    FatherClassName.method(self,arguments)
    (2)Python中采用了C3线性化算法去检索父类,保证每个父类只检索一次,以避免检索过程陷入死循环
""")


# 继承:inherit

class FatherClass:
    """ father class and children class inherit relation"""

    __operationActivity = "scientist"

    # 拓展init方法,完成初始化工作;将传入的参数赋值给成员变量name,age
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 普通的成员方法
    def showFatherInfo(self):
        # 类的私有化成员属性,在本类中可以使用self.属性名的方式访问
        print("operationActivity: ", self.__operationActivity)
        return self.name, self.age

    # 提供一个公有的方法给外界访问类私有属性
    def getOperationActivity(self):
        return self.__operationActivity


# 单继承
class GirlChildrenClass(FatherClass):
    """A GirlChildrenClass Class"""

    def showFatherInfo(self):
        # 子类重写父类的方法,并调用父类被重写的方法
        FatherClass.showFatherInfo(self)
        print("女孩叫:", self.name, " 年龄: ", self.age)


myGirlFather = GirlChildrenClass('小米', 200)
myGirlFather.showFatherInfo()
print("访问类属性__operationActivity私有属性: ", myGirlFather.getOperationActivity())
print("子类的相关属性: ", myGirlFather.__dict__)
print("""
    子类不能继承父类的私有属性:
""")
print("-------------------------------------------------------------------------------------")

print()
print('-----------------------------------------多继承----------------------------------')


# 定义一个字类
class FemaleFatherClass(FatherClass):
    """A FemaleFatherClass class"""

    def showFatherInfo(self):  # 定义一个成员函数
        print(self.name, ":", self.age, ", female")  # 该成员函数返回成员的信息
        FatherClass.showFatherInfo(self)  # 调用其父类的showFatherInfo方法


# 定义一个子类
class RetireFatherClass(FatherClass):
    """A RetireFatherClass class"""

    def showFatherInfo(self):  # 定义成员函数
        FatherClass.showFatherInfo(self)  # 调用父类的showFatherInfo方法
        print("retire worker")  # 该成员函数返回该类的成员变量


# 多继承
class ThisFatherClass(FemaleFatherClass, RetireFatherClass):
    """A ThisFatherClass class"""  # 定义这类的说明字符串

    def showFatherInfo(self):  # 定义一个成员函数
        print("the member detail as follow:")  # 该成员函数返回这类的成员变量
        # 调用父类的showFatherInfo方法
        FemaleFatherClass.showFatherInfo(self)
        RetireFatherClass.showFatherInfo(self)


myThisInfo = ThisFatherClass("杨哥", 26)
myThisInfo.showFatherInfo()
print()
print()
print()
print("myThisInfo.showFatherInfo()输出如下内容:")
print("""
    the member detail as follow:
    杨哥 : 26 , female
    operationActivity:  scientist
    operationActivity:  scientist
    retire worker
""")

print("""
   通过输出内容,发现父类FatherClass类中的showFatherInfo方法被调用了两从,在实际编程中
   这种父类函数被自动调用多次的情况一定要避免,如果showFatherInfo方法时一些申请资源之类的操作
   这种写法会导致资源泄露,会严重影响程序的性能;
   针对这种情况:
       通常我们使用super函数,实现多继承中父类的调用
""")


# 定义一个字类
class SubFemaleFatherClass(FatherClass):
    """A FemaleFatherClass class"""

    def showFatherInfo(self):  # 定义一个成员函数
        print(self.name, ":", self.age, ", female")  # 该成员函数返回成员的信息
        super().showFatherInfo()  # 调用其父类的showFatherInfo方法


# 定义一个子类
class SubRetireFatherClass(FatherClass):
    """A RetireFatherClass class"""

    def showFatherInfo(self):  # 定义成员函数
        super().showFatherInfo()  # 调用父类的showFatherInfo方法
        print("retire worker")  # 该成员函数返回该类的成员变量


# 多继承
class SubThisFatherClass(SubFemaleFatherClass, SubRetireFatherClass):
    """A ThisFatherClass class"""  # 定义这类的说明字符串

    def showFatherInfo(self):  # 定义一个成员函数
        print("super()函数返回值: ", super())
        print("the member detail as follow:")  # 该成员函数返回这类的成员变量
        # 调用父类的showFatherInfo方法
        super().showFatherInfo()


print("""
   注意:
      使用super函数时,对父类的方法使用会自动传入self.无需再传入self,否则报错;
      
""")
print('----------------------------------------------')
myThisInfo = SubThisFatherClass("杨大侠", 20)
myThisInfo.showFatherInfo()

print("""  使用super()函数后,多继承父类的showFatherInfo()方法只会调用一次
    super()函数返回值:  <super: <class 'SubThisFatherClass'>, <SubThisFatherClass object>>
    the member detail as follow:
    杨大侠 : 20 , female
    operationActivity:  scientist
    retire worker
""")


七:父子类面向对象编程思想运行效果


D:\program_file_worker\anaconda\python.exe D:\program_file_worker\python_source_work\SSO\grammar\oop\ClassInheritBaseClass.py 
类的认知:
Python中类的继承关系: 派生与继承时针对子类与父类而言
-----------------------------------认知升维----------------------------------------
-----------------------------------来认识覆盖|重写----------------------------------

    (1)学习java的小伙伴知道,覆盖是指子类重写父类的方法,重写发生在子类与父类之间,当父类的方法实现的业务不能满足我们需要的时候,此时我们可以通过重写
    父类的方法来实现我们的业务逻辑;通过拓展父类的方法,可以在不改变父类的前提下,不会影响其他继承同一父类的类产生影响;
    当子类的方法与父类的方法同名时且参数表列相同时,父类的方法也将失效; 通常子类覆写父类方法的同时,需要调用下父类的被覆写的方法;
    这种情况下,可以通过以下的方式调用父类方法:
    FatherClassName.method(self,arguments)
    (2)Python中采用了C3线性化算法去检索父类,保证每个父类只检索一次,以避免检索过程陷入死循环

operationActivity:  scientist
女孩叫: 小米  年龄:  200
访问类属性__operationActivity私有属性:  scientist
子类的相关属性:  {'name': '小米', 'age': 200}

    子类不能继承父类的私有属性:

-------------------------------------------------------------------------------------

-----------------------------------------多继承----------------------------------
the member detail as follow:
杨哥 : 26 , female
operationActivity:  scientist
operationActivity:  scientist
retire worker

myThisInfo.showFatherInfo()输出如下内容:

    the member detail as follow:
    杨哥 : 26 , female
    operationActivity:  scientist
    operationActivity:  scientist
    retire worker


   通过输出内容,发现父类FatherClass类中的showFatherInfo方法被调用了两从,在实际编程中
   这种父类函数被自动调用多次的情况一定要避免,如果showFatherInfo方法时一些申请资源之类的操作
   这种写法会导致资源泄露,会严重影响程序的性能;
   针对这种情况:
       通常我们使用super函数,实现多继承中父类的调用


   注意:
      使用super函数时,对父类的方法使用会自动传入self.无需再传入self,否则报错;
      

----------------------------------------------
super()函数返回值:  <super: <class 'SubThisFatherClass'>, <SubThisFatherClass object>>
the member detail as follow:
杨大侠 : 20 , female
operationActivity:  scientist
retire worker

Process finished with exit code 0
 

猜你喜欢

转载自blog.csdn.net/u014635374/article/details/133417520