Python 类的知识点

什么是类?
类明明的话,大驼峰小驼峰如:BigBoss
类属性:成员都具备的特质
实例属性:一般放在init中初始化

class People(Object):
	weight = 188
	def __init__(self,name):
	self.name = name
	pass

这个Peole就是一个类
weight就是类属性,使用People.weight来获取
什么是对象?

p = People("xiaoming")

这个p就是对象
p.name就是其中一个实例属性
基础的知识点在这里就不重复说了
类的特点就是封装继承和多态

__init__ __del__

每次我们创建对象之后,python解释器就会自动调用__init__方法;
当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法
创建对象时,此对象的引用计数就会+1
当有1个变量保存了对象的引用时,此对象的引用计数就会加1
当使用del删除变量指向的对象时,如果对象的引用计数不会1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除

import time
class Animal(object):

    # 初始化方法
    # 创建完对象后会自动被调用
    def __init__(self, name):
        print('__init__方法被调用')
        self.__name = name


    # 析构方法
    # 当对象被删除时,会自动被调用
    def __del__(self):
        print("__del__方法被调用")
        print("%s对象马上被干掉了..."%self.__name)

我们可以执行一下代码,验证如下问题:

# 创建对象
dog = Animal("哈皮狗")

# 删除对象
del dog


cat = Animal("波斯猫")
cat2 = cat
cat3 = cat

print("---马上 删除cat对象")
del cat
print("---马上 删除cat2对象")
del cat2
print("---马上 删除cat3对象")
del cat3

结果如下:
在这里插入图片描述

继承

class Animal(object):

    def __init__(self, name='动物', color='白色'):
        self.__name = name
        self.color = color

    def __test(self):
        print(self.__name)
        print(self.color)

    def test(self):
        print(self.__name)
        print(self.color)



class Dog(Animal):
    def dogTest1(self):
        #print(self.__name) #不能访问到父类的私有属性
        print(self.color)


    def dogTest2(self):
        #self.__test() #不能访问父类中的私有方法
        self.test()


A = Animal()
#print(A.__name) #程序出现异常,不能访问私有属性
print(A.color)
#A.__test() #程序出现异常,不能访问私有方法
A.test()

print("------分割线-----")

D = Dog(name = "小花狗", color = "黄色")
D.dogTest1()
D.dogTest2()
  • 私有的属性,不能通过对象直接访问,但是可以通过方法访问
  • 私有的方法,不能通过对象直接访问
  • 私有的属性、方法,不会被子类继承,也不能被访问
  • 一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用
    简而言之一句话:
    私有属性可以通过方法被访问,但是不能通过对象被访问,私有属性也不能被继承
    多继承的顺序。当然不知道的时候使用使用print(类名.__mro__)
    一般情况下,class Son(A,B)是先继承A,之后继承B的

重写父类方法与调用父类方法

  • 所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
  • 不重写的话,就会直接继承
  • 那一般为什么要重写呢,就是因为我们在父类的基础上有新加了一些东西,所以我们在原来的基础上,写新的东西。
  • super()就是代表父类 super().方法()就代表要调用的那个方法。
#coding=utf-8
class Cat(object):
    def sayHello(self):
        print("halou-----1")


class Bosi(Cat):

    def sayHello(self):
        print("halou-----2")

bosi = Bosi()

bosi.sayHello()
  • 调用父类的方法
#coding=utf-8
class Cat(object):
    def __init__(self,name):
        self.name = name
        self.color = 'yellow'


class Bosi(Cat):

    def __init__(self,name):
        # 调用父类的__init__方法1(python2)
        #Cat.__init__(self,name)
        # 调用父类的__init__方法2
        #super(Bosi,self).__init__(name)
        # 调用父类的__init__方法3
        super().__init__(name) 
        # 上面的意思就是调用父类方法中的init这个方法

    def getName(self):
        return self.name

bosi = Bosi('xiaohua')

print(bosi.name)
print(bosi.color)

多态

类属性和实例属性

类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有
类属性还分公有的类属性和私有的类属性
对于公有的类属性,在类外可以通过类对象和实例对象访问
如下示例:

  • 类属性
class People(object):
    name = 'Tom'  #公有的类属性
    __age = 12     #私有的类属性

p = People()

print(p.name)           #正确
print(People.name)      #正确
print(p.__age)            #错误,不能在类外通过实例对象访问私有的类属性
print(People.__age)        #错误,不能在类外通过类对象访问私有的类属性
  • 实例属性(对象属性)
    用类的属性方法是访问不了的
class People(object):
    address = '山东' #类属性
    def __init__(self):
        self.name = 'xiaowang' #实例属性
        self.age = 20 #实例属性

p = People()
p.age =12 #实例属性
print(p.address) #正确
print(p.name)    #正确
print(p.age)     #正确

print(People.address) #正确
print(People.name)    #错误
print(People.age)     #错误
  • 通过实例(对象)去修改类属性
class People(object):
    country = 'china' #类属性


print(People.country)
p = People()
print(p.country)
p.country = 'japan' 
print(p.country)      #实例属性会屏蔽掉同名的类属性
print(People.country)
del p.country    #删除实例属性
print(p.country)

如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

静态方法和类方法还有实例方法

实例方法很简单就是通过实例去调用方法,类方法是无法调用的,什么是类方法,如下面那个,就是Peole.方法的形式就是类方法
类方法的话,

类方法

是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以’cls’作为第一个参数的名字,就最好用’cls’了),能够通过实例对象和类对象去访问。

  • 这个cls就是class的简写
  • 调用,类名.方法,实例.方法都是可以的
class People(object):
    country = 'china'

    #类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country

p = People()
print(People.getCountry())
print(p.getCountry())

结果如下:
在这里插入图片描述

  • 类方法还有一个用途就是可以对类属性进行修改:
class People(object):
    country = 'china'

    #类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country

    @classmethod
    def setCountry(cls,country):
        cls.country = country


p = People()
print p.getCountry()    #可以用过实例对象引用
print People.getCountry()    #可以通过类对象引用

p.setCountry('japan')   

print p.getCountry()   
print People.getCountry()
静态方法
  • 需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数
  • 也就是不需要self这个占位,也就是刚刚好放在类下面的普通函数,和实例的关系不大。
  • 你加self那就变成了实例方法了
  • 关于调用,使用self.方法和 类名.方法都是可以的
class People(object):
    country = 'china'

    @staticmethod
    #静态方法
    def getCountry():
        return People.country


print People.getCountry()

总结
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用

__new__和__init__的作用

直接总结一下吧

  • __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

  • __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

  • __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

  • 我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节

class A(object):
    def __init__(self):
        print("这是 init 方法")

    def __new__(cls):
        print("这是 new 方法")
        return object.__new__(cls)

A()

结果如下:

在这里插入图片描述

单例模式

举个常见的单例模式例子,我们日常使用的电脑上都有一个回收站,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。因此回收站是单例模式的应用。

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。

# 实例化一个单例
class Singleton(object):
    __instance = None

    def __new__(cls, age, name):
        #如果类数字能够__instance没有或者没有赋值
        #那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时
        #能够知道之前已经创建过对象了,这样就保证了只有1个对象
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

a = Singleton(18, "dongGe")
b = Singleton(8, "dongGe")

print(id(a))
print(id(b))

a.age = 19 #给a指向的对象添加一个属性
print(b.age)#获取b指向的对象的age属性

从如下结果中可以看到,指针都是指向同一内存,改变一个实例,不管a还是b都会,都会一致的改变。
在这里插入图片描述

  • 创建单例时,只执行1次__init__方法
# 实例化一个单例
class Singleton(object):
    __instance = None
    __first_init = False

    def __new__(cls, age, name):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def __init__(self, age, name):
        if not self.__first_init:
            self.age = age
            self.name = name
            Singleton.__first_init = True


a = Singleton(18, "dongGe")
b = Singleton(8, "dongGe")

print(id(a))
print(id(b))


print(a.age)
print(b.age)

a.age = 19
print(b.age)

在这里插入图片描述

类的一些魔法函数

def __repr__(self):

def  __repr__(self):
	''' 返回对象打印出来的效果,名字固定的用法'''
	return self.属性

getatter()

  • 获取属性,动态获取某个属性的函数
  • 使用方法
    • getatter(对象或者类名,属性名称,当没有这个属性的值时,需要提供一个默认值)
      在这里插入图片描述

setatter()

不管原来有没有这个属性和这个值,都会赋值给它
使用方法如下:
在这里插入图片描述
在这里插入图片描述

补充

  • 只要在初始化中__init__定义的变量,在类的函数中,就可以直接用,不需要在函数的参数里面进行说明。

在工作中,逐渐学会了这样的一种用法:感觉很高级,但是在大神面前,那肯定不值一提。

类里面嵌套类
万物皆对象(所以类当然是啦)
  • 其实这种方式有很多应用,就先记录在这里,以后用的时候,希望自己能想到。
class Upload(object):
	pass

class Dotest(object):
	
	def __init__(self):
		self.upload = Upload()

有时候,我们A类里面需要使用B类很多东西的时候,又不对其进行继承,就可以使用这种初始化吧。

举一个很小的例子吧:

class Case:
    """
    测试用例封装类
    """

    def __init__(self):
        self.id = None
        self.url = None
        self.data = None
        self.title = None
        self.method = None
        self.expected = None
        self.actual = None
        self.result = None

class DoExcel:
    file_name = None

    def __init__(self, file_name):
        try:
            # 操作的文件
            self.file_name = file_name
            # 实例化一个workbooK对象
            self.workbook = openpyxl.load_workbook(filename=file_name)
            # 异常处理如何做
        except FileNotFoundError as e:
            # 文件未找到异常处理
            print('{0} not found, please check file path'.format(file_name))
            raise e

    def get_cases(self, sheet_name):
        sheet_name = sheet_name
        sheet = self.workbook[sheet_name]  # 获取sheet
        max_row = sheet.max_row  # 获取sheet最大行数
        cases = []  # 定义一个列表,用来存放即将要放进去的测试用例
        for r in range(2, max_row + 1):  # for 循环,从第二行开始遍历
            case = Case()  # 实例化一个case对象,用来存放测试数据
            case.id = sheet.cell(row=r, column=1).value  # 取第r行,第1格的值
            case.title = sheet.cell(row=r, column=2).value  # 取第r行,第2格的值
            case.url = sheet.cell(row=r, column=3).value  # 取第r行,第3格的值
            case.data = sheet.cell(row=r, column=4).value  # 取第r行,第4格的值
            case.method = sheet.cell(row=r, column=5).value  # 取第r行,第5格的值
            case.expected = sheet.cell(row=r, column=6).value  # 取第r行,第6格的值
            if type(case.expected) == int:
                case.expected = str(case.expected)
            cases.append(case)  # 将case放到cases 列表里面

        return cases  # for 循环结束后返回cases列表


上面的代码已经做了详细的注释,主要是实现一个多个测试用例的,其实最后调用就会得到这样的数据

cases = [case{xxx1},case{xxx2},case{xxx3}...]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值