python初学一(面向对象编程)

  •     ① 类名不能调用类的普通方法,可以调用类方法与静态方法

一、类与对象:

           1、特性:① 类是对象的类型,对象是类的实例化。类与类之间可以嵌套继承。

                            ② 类是对函数的一种封装。

           2、类的定义:

                             属性: 类属性和对象属性

                             方法: 初始化方法,普通方法,静态方法,类方法                           

python初学一(面向对象编程)_第1张图片

               理解:面向对象的函数式设计:

python初学一(面向对象编程)_第2张图片

            #面向对象
class Person:
    county = 'China'                    # 类属性        类和所有对象都能够调用,用 . 的方式。
    def __init__(self,name,age,sex):          # 构造函数(初始化函数)
        self.name = name               # 第一个name是属性(对象字典的key),第二个name是形参(具体对象的values)
        self.age = age                 # 实例变量
        self.sex = sex
    def func(self,orther,color='黄皮肤'):
        print('%10s 年龄 %d 岁,性别 %s %s' %(self.name,self.age,self.sex,color)) ----- color 是一个普通形参 , orther 是一个对象形参(注意这两者的使用方式)
              #  得到对象需要类的实例化,实例化时需要传递对象的具体特征,必须是初始化函数定义过的。
        print('%s打了%s' %(self.name,orther.name))  ----- 传入的形参 orther是一个对象(由这个类实例化产生的)
Person.func()  -----错误:  不能用类名调用参数
Peo = Person("张",22,'男性')
people_me = Person('刘',22,'男性')   -------  类的 实例化
people_me.func(Peo)            ---------- 对象调用类的方法,并传入一个对象
people_me.func(Peo,color= '白皮肤')   --------- 对象调用类的方法,并传入一个对象 和 一个普通实参

#                    类属性
print(Person.county)
print(people_me.county)

 

二、 类属性(类变量)与对象属性:增删改查

                       

python初学一(面向对象编程)_第3张图片

                           

                        类属性 用类名.属性名来调用,对象属性在类外面用对象名.属性名来调用 ,在类里面用self.属性名来调用。

 

                1、类属性:类变量

                    (1)  变量:类变量在整个实例化的对象中是公用的类变量定义在类中且在函数体之外。类变量通常不作为

                                   实例变量使用。

                    (2)类属性的增删改查:

                         getattr、setattr、hasattr、delattr :这些方法是系统方法,同样适用与对象属性

                        ①类属性的查看:类名.属性名、对象.属性名、getattr(类名,属性名)

class Person:
    county = 'China'
    def __init__(self,):
        pass
people1 = Person()
print(Person.county)         通过类名
print(getattr(Person,"county"))   通过getattr
print(people1.county)      通过对象
print(getattr(people1,"county")
结果:
China
China
China
China

                     ②类属性的增加与修改:setattr

class Person:
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

Person.county = 'China'                直接通过 类名  添加类属性

还可以:
setattr(Person,'county','China')          通过 getattr 类名

                    ③类属性的删除:delattr / del

class Person:
    county = 'China'
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

delattr(Person,'county')       --------- delattr(类名,属性名)
del Person.county              --------- del 关键字删除

                  ④类属性是否存在:hasattr

class Person:
    county = 'China'
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

hasattr(Person.county) >>>>>> bool值
         

           2、对象属性:

                    (1)对象属性的理解:

                               类实例化对象的属性。

                    (2)对象属性的增删改查:

                                与类属性相似,将 类名 换为 对象名:


             对象属性不像类属性,对象属性的更改只对这个对象起作用,其他类对象不能获取。
class Person:
    county = 'China'
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge
people1 = Person('张三','20')
 获取对象属性:
1、print(getattr(people1,'name'))
2、print(people1.name)
 添加或修改对象属性:没有值时会自动添加,类似字典的 setdefault 方法。
1、setattr(people1,'addr','北京')
   print(people1.name)
2、people1.addr = '北京'
   print(people1.name)
删除对象属性:delattr(对象名,对象属性)
             或者 del 对象名.对象属性名
判断是否存在对象属性:hasattr

 

python初学一(面向对象编程)_第4张图片

三、类中的普通方法:            

class Person:
    county = 'China'                    # 类属性        类和所有对象都能够调用,用 . 的方式。
    def __init__(self,name,age,sex):          # 构造函数(初始化函数)
        self.name = name               # 第一个name是属性(对象字典的key),第二个name是形参(具体对象的values)
        self.age = age                 # 实例变量
        self.sex = sex
    def func(self,color='黄皮肤'):     -------- 普通方法
        print('%10s 年龄 %d 岁,性别 %s %s' %(self.name,self.age,self.sex,color))

四、python内置类属性:

           1、内置类属性的介绍:

python初学一(面向对象编程)_第5张图片

        1、__doc__  、 __dict__  与 __bases__ 

内置类属性
print(mc.__dict__)   {'restaurant_name': '麦当劳', 'cuisine_type': '快餐'} ---- 结果是对象属性 组成的字典
print(Restaurant.__dict__)  ---------- 结果是   类和对象属性   组成的字典
==========================================================================================
print(Restaurant.__doc__)   ---------- 显示类介绍
print(mc.__doc__)
==========================================================================================
第一种用法:
print(Restaurant.__name__)    ------ 打印类名 (Restaurant)
第二种:                   
print(__name__)    # 结果:1、本文件打印  __main__ 2、其他文件引用: 类名   
if __name__=='__main__':     -------  模块导入时,__name__ 的用法
    print('专有')
===========================================================================================
__bases__ : 类的所有父类构成元素   (包含了以个由所有父类组成的元组)
print(Restaurant.__bases__)        # 基类

             2、 __name__:

python初学一(面向对象编程)_第6张图片

 

python初学一(面向对象编程)_第7张图片

 五、习题例题:

             1、如何记录实例化次数:

                如何查看实例化的次数?
class people():
    num=0
    def __init__(self):
        self.name='杨幂'
        people.num+=1

yangmi1=people()
yangmi2=people()
yangmi3=people()
print(people.num)          # 3

            2、实例:

1.餐馆:创建一个名为Restaurant的类,其方法__init__()设置两个属性:
restaurant_name 和 cuisine_type(烹饪)。
创建一个名为 describe_restaurant()方法和一个名为open_restaurant ()方法,
其中前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。
根据这个类创建一个名为restaurant的实例,分别打印其两个属性,再调用前述两个方法。
三家餐馆:根据你为完成练习1而编写的类创建三个实例,并对每个实例调用方法 describe_restaurant()。
-------------------------------------------------------------------------------------------
3.就餐人数:在为完成练习1而编写的程序中,添加一个名为number_served的属性,并将其默认值设置为0。
打印有多少人在这家餐馆就餐过,然后修改这个值并再次打印它。
添加一个名为set_number_served()的方法,它让你能够设置平日就餐人数。
调用这个方法并向它传递一个值,然后再次打印这个值。
添加一个名为increment_number_served()的方法,它让你能够将就餐人数递增.
调用这个方法并向它传递一个这样的值:你认为这家餐馆每天可能接待的就餐人数
class Restaurant:
    '''这是一个餐馆类:  (用来干嘛干嘛)'''
    def __init__(self,restaurant_name,cuisine_type,number_served=0):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type
        self.number_served = number_served
    def describe_restaurant(self):
        print('餐馆的名字是%s,菜的类型是%s'%(self.restaurant_name,self.cuisine_type))
    def open_restaurant(self):
        print('正在营业')
    def set_number_served(self,n):
        self.number_served = n              #setattr(obj,"key",value)
        print('现在餐馆中就餐的人数是%d人'%self.number_served)
    def increment_number_served(self,add_num):
        self.number_served+=add_num
        print('现在餐馆中就餐的人数是%d人'%self.number_served)
    def reset_login_attempts(self):
        self.number_served=0
        print('人数清空')

 六、类继承:

      1、类继承的特性:

  •           (1)程序中当我们定义一个class的时候,可以从某个现有的class继承,新的class称之为子类(Subclass),
  •                     而被继承的 class称之为基类、父类或超类子类继承了其父类的所有属性和方法(私有属性和方法除外),
  •                     同时还可以定义自己的属性和方法。
  •           (2)父类不能够访问子类。
  •           (3)目的:减少重复代码。
  •           (4)子类调用父类的方法:① 父类.方法名()    ② 利用 super(某层级类名,self).方法名()

      2、子类继承顺序(同级)和方法重写(override):

            ① 子类继承的格式:

python初学一(面向对象编程)_第8张图片

         ②子类继承顺序(同级)例子: 

class C():
    def c(self):
        print('c')
    def a(self):
        print('c2')
class A():
    def a(self):
        print('a')
    def c(self):
        print('a2')
class B(C,A):        ------- 同级继承的类名 排在左边的优先显示
    def b(self):
        print('b')
    def a(self):     ------- override 方法重写,子类方法覆盖父类方法,优先执行子类的方法
        print('b2')

ob = B()            
ob.b()
ob.c()
ob.a()

      2、子类添加子类属性,super():

  •          特点:① super() 有两个参数 ,第一个参数是某个继承层级的类名(默认是本层级的类名),第二个参数是 self;
  •                          结果:它指的是 某一层级的父类

           (1)实例:

1.餐馆:创建一个名为Restaurant的类,其方法__init__()设置两个属性:
restaurant_name 和 cuisine_type(烹饪)。
创建一个名为 describe_restaurant()方法和一个名为open_restaurant ()方法,
其中前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。
根据这个类创建一个名为restaurant的实例,分别打印其两个属性,再调用前述两个方法。
三家餐馆:根据你为完成练习1而编写的类创建三个实例,并对每个实例调用方法 describe_restaurant()。
-------------------------------------------------------------------------------------------
3.就餐人数:在为完成练习1而编写的程序中,添加一个名为number_served的属性,并将其默认值设置为0。
打印有多少人在这家餐馆就餐过,然后修改这个值并再次打印它。
添加一个名为set_number_served()的方法,它让你能够设置平日就餐人数。
调用这个方法并向它传递一个值,然后再次打印这个值。
添加一个名为increment_number_served()的方法,它让你能够将就餐人数递增.
调用这个方法并向它传递一个这样的值:你认为这家餐馆每天可能接待的就餐人数
class Restaurant:
    '''这是一个餐馆类:  (用来干嘛干嘛)'''
    def __init__(self,restaurant_name,cuisine_type,number_served=0):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type
        self.number_served = number_served
    def describe_restaurant(self):
        print('餐馆的名字是%s,菜的类型是%s'%(self.restaurant_name,self.cuisine_type))
    def open_restaurant(self):
        print('正在营业')
    def set_number_served(self,n):
        self.number_served = n              #setattr(obj,"key",value)
        print('现在餐馆中就餐的人数是%d人'%self.number_served)
    def increment_number_served(self,add_num):
        self.number_served+=add_num
        print('现在餐馆中就餐的人数是%d人'%self.number_served)
    def reset_login_attempts(self):
        self.number_served=0
        print('人数清空')
================================= 第一种方法 ====================================================
在子类中定义 __init__() 函数,但这样会覆盖父类中__init__()属性(除非将父类中的所有属性重写覆盖)
list1 = ['辣的','咸的','甜的']
class IceCreamStand(Restaurant):
    def __init__(self,flavors):
        self.flavors = flavors
    def show_flavors(self):
        print('味道: “{}”、“{}”、“{}”'.format(*self.flavors))
admin1 = IceCreamStand(list1)
admin1.show_flavors()
==================================== 第二种方法:父类.方法名()=========================================

class IceCreamStand(Restaurant): 
    def __init__(self,restaurant_name, cuisine_type,flavors,number_served=1): ----- flavors是添加的子类属性。
        父类名.__init__(self,restaurant_name, cuisine_type, number_served=1) ----- 这里面需要填写 self ,相当于将父类中 __init__() 中的代码复制到 子类中
        self.flavors=flavors  ---- 添加子类属性
    def describe_restaurant(self):  
        print('这家冰激凌小店的名字是%s,它的烹饪类型是%s,冰激凌口味包含%s'%(self.restaurant_name,self.cuisine_type,self.flavors))

==================================== 第三种方法:super()用法 ========================================

1.冰淇淋小店重写 2. super()添加对象属性 flavors
class IceCreamStand(Restaurant): 
    def __init__(self,restaurant_name, cuisine_type,flavors,number_served=1): ----- flavors是添加的子类属性。
        super().__init__(restaurant_name, cuisine_type, number_served=1)  ---- super()默认会传入当前层类名与self参数,因此__init__()里面不必写self参数
        self.flavors=flavors     --------- 添加子类属性
    def describe_restaurant(self):   -------- 重写父类
        print('这家冰激凌小店的名字是%s,它的烹饪类型是%s,冰激凌口味包含%s'%(self.restaurant_name,self.cuisine_type,self.flavors))
if __name__ == '__main__':
    Ice1=IceCreamStand('星吧乐','手工制作',['辣的','咸的','甜的','酸的','苦de']) ----传参数时,父类与子类新加的对象属性都要传。
    Ice1.describe_restaurant()
    Ice1.get_info() 


          ( 2 ) 过程解析 :

python初学一(面向对象编程)_第9张图片

    3、子类与父类 类型判断(两个系统函数isinstance()、type()):

class A:
    def func1(self):
        pass
class B(A):
    def func2(self):
        pass

print(isinstance(B(),A))      # 子类父类 类型相同
print(type(B()) == type(A))   # 判断子类父类 类型不同
结果:
True
False

七、访问限制:

    1、私有属性(类属性和对象属性)的特性:private

            (1) 私有类属性:

            (2) 私有对象属性:       

  •                             ① 为了保护属性不被随意修改和访问,可以将属性定义为私有属性
  •                             ② 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例变量
  •                                 名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问且不可继承,
  •                                 这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮,
  •                                 且可以对参数做检查(if elif),避免传入无效的参数

     2、受保护的属性:protected

  •                 特点:① 与私有属性相似,属性名前加一个下划线 _ 
  •                            ② 可以继承与内部操作,外部不可使用

     3、代码:

class Person:
    __county = 'China'                  # 私有类属性

    def __init__(self, newName, newAge):
        self.__name = newName           # 私有对象属性
        self.age = newAge 
    def func(self):                     # 普通方法
        print(self.__name)  
    def __func(self):                   # 私有方法
        pass          

print(Person.__county)      #            报错,无法访问
people1 = Person('私有属性','正常属性')
print(people1.__name)      #             报错,无法访问
print(people1.age)         #              正常属性


  如果赋值的话相当于添加了新__name,并没有获得私有对象属性 __name. 

people1.__name = '赋值'
print(people1.__name)     结果   赋值
people1.func()            结果   私有属性      ,即内部还是调用原有的私有属性 __name。

                 强行访问    对象名._类名__属性名
print(people1._Person__name)   #  私有属性
                
                 通过定义普通方法来访问

class Person:
    __county = 'China'                  # 私有类属性
    def __func(self):
        return '我是私有方法'
    def get_country(self):              # 定义一般方法访问 私有类变量
        return self.__county
    def get_func(self):                  # 定义一般方法访问 私有方法
        return self.__func()
people1 = Person()
print(people1.get_country())
print(people1.get_func())

八、类方法与静态方法:

      1、普通方法:     

python初学一(面向对象编程)_第10张图片

 

       2、静态方法:

  •                    特点:① 对象与类名均可调用,无需传参self与cls,区别于类方法(类方法必须传cls.属性名)
  •                               ② 不需要实例化(常常用类名调用)

python初学一(面向对象编程)_第11张图片

 

      3、类方法:对象与类均可调用,必须传参cls。

  •                        特点:① 常常用类名调用,必须传参cls
  •                                   ② 调用类属性时 需要用 cls.属性名

python初学一(面向对象编程)_第12张图片

      4、代码:

class Person:
    county = 'China'
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.__age = age                私有对象属性
    def get_info(self):
        print('%s %s %s 岁!' %(self.name,self.sex,self.__age))
    @staticmethod                         静态方法,不需要传入self,因此不能用self.属性名。
    def A():
        print("我是静态方法 %s" %Person.county)
    @classmethod
    def B(cls):                           
        print('我是类方法,需要用cls.属性名 %s' %cls.county)    ------ 需要用cls.属性名
people1 = Person('刘德华','男性','54')
people1.get_info()          
print(Person.county)        ------ China
print(people1.county)       ------ China
people1.A()                 ------ 我是静态方法 China
Person.A()                  ------ 我是静态方法 China
people1.B()                 ------ 我是类方法,需要用cls.属性名 China
Person.B()                  ------ 我是类方法,需要用cls.属性名 China

              https://blog.csdn.net/qq_16555103/article/details/86570153  ----------------- 面向对象的例子 

 

你可能感兴趣的:(AI-python_基础)