Python——类

前言

在了解什么是Python类之前,先来了解一下什么是面向对象编程:

一、什么是面向对象编程

1、面向对象编程(oop)是一种程序设计思想。oop把对象作为程序的基本单元,一个对象包含数据和操作数据的函数

2、在python中,所有数据类型都被视为对象,也可以自定义对象。自定义对象数据类型就是面向对象中类的概念

二、面向对象术语简介

术语意义
类(class)用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例
方法类中定义的函数
类变量(属性)类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体(方法)之外。类变量通常不作为实例变量使用,类变量也称作属性
数据成员类变量或者实例变量用于处理类及其实例对象的相关的数据
方法重写如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写
实例变量定义在__init__方法中的变量,只作用于当前实例的类
继承即一个派生类(derived class)继承基类(base class)的字段和方法
实例化创建一个类的实例,类的具体对象。一个类可以实例化出无数个对象
对象通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法
多态对不同的类使用不同的工作
封装对外部世界隐藏对象的工作细节

三、Python类

Python的类提供了面向对象编程的所有标准特性:
⑴类继承机制允许多个基类,派生类可以覆盖它基类的任何方法,一个方法可以调用基类中相同名称的的方法
⑵对象可以包含任意数量和类型的数据
⑶和模块一样,类也拥有Python天然的动态特性:它们在运行时创建,可以在创建后修改

类的定义

class MyStudent:		# 定义一个类
    def __init__(self,name,age,sex): #类的构造函数,用于初始化类的内部状态,为类的属性设置默认值
        self.name = name	# 定义类的属性
        self.age  = age		# 定义类的属性
        self.sex  = sex		# 定义类的属性
        self.__secret = 0	#私有变量
    
    def studentName(self,name):
        print(f'student name is{self.name}')

t = MyStudent('小王',11,0)	# 实例化一个对象t
t.studentName('小李')	#对象调用studentName方法

1.一般使用 class 语句来创建一个新类,class之后为类的名称(通常首字母大写)并以冒号结尾;
2.类中可以定义所使用的方法,类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self;
3.创建类时,可以定义一个特定的方法,名为__init__(),只要创建这个类的一个实例就会运行这个方法。类似于C++中的构造方法,可以通过__init__()方法传递参数。
4.self 代表类的实例,self 在定义类的方法时是必须有的,用来实例化类定义的函数和变量;
5.__private_attrs 两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。

classmethod类方法

类方法(装饰器),第一个参数是cls,代表这个类(注意不是类实例),常用来调用类级方法(如系统方法跟静态方法,类方法等)来进行预处理,然后返回预处理后的类。效果就像另一个构造函数一样(实际上并不是)

class info(object):

  @classmethod
  def sayclassmethod(cls):

    print 'say %s' % cls

  def saymethod(self):

    print 'say %s' % self


test = info()
test.saymethod()##实例调用方法
test.sayclassmethod()##实例调用类方法
info.saymethod(test)##类调用实例方法
info.sayclassmethod()##类调用类方法

使用@classmethod是为了处理一些__init__处理不了的赋值问题(一般是参数不对应),可以当成有第二、第三个__init__方法,或者是C++中的构造函数,要通过类名才能显示调用。

staticmethod静态方法
使用@staticmethod目的之一是为了增加可读性,不需要参数self的方法都可以加上@staticmethod增加可读性,因为,这个方法是类级别的,在调用时要使用类名。

继承类定义
1.单继承

class <类名>(父类名)
<语句>

class A:
    #不管是本类还是子类 只要实例化 就会调用(前提是 没有被子类的__init__覆盖)
    def __init__(self,n,a,s):
        self.name = n
        self.age = a
        self.sex = s
    def speak(self):
        print("我现在{}岁了 我叫{} 我的性别是{}".format(self.age,self.name,self.sex))
# a = A('张三',18,'男')
# print(a.name)
# a.speak()
class B(A):
    grade = ''
    def __init__(self,name,age,sex,grade):
        print('我是子类的__init__')
        self.grade = grade
        A.__init__(self,name,age,sex)
    def speak(self):
        A.speak(self)
        print("我今年{} 我叫{} 我的成绩是{}".format(self.age,self.name,self.grade))
b = B('张三',18,'男',60)
# print(b.name)
# print(b.__dict__)
b.speak()

2.类的多重继承
class 类名(父类1,父类2,…,父类n)
<语句1>

需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索,即方法在子类中未找到时,从左到右查找父类中是否包含方法

class A:
    def speak(self):
        print('我是A类的speak方法')
    def a(self):
        print('a')

class B:
    def speak(self):
        print('我是B类的speak方法')
    def b(self):
        print('b')

class C(A,B):
    def speak(self):
        super().speak() #还是从左往右找..
        #super(C,self).speak()
        # super(A,self).speak()
        # super(B,self).speak()

四、类的专业方法

首先需要理解的是,两个下划线开头的函数是声明该属性为私有,不能在类的外部被使用或访问
1__init__()
类似于构造函数,可以通过__init__()方法传递参数,但是一个参数必须为self,后续参数为自己定义。

#!/usr/local/bin/python
class Study:
        def __init__(self,name=None):
                self.name = name
        def say(self):
                print self.name
study = Study("Badboy")
study.say()

2__del__()
类似于析构函数,析构函数往往是用来是否内存,哪怕不写也会默认调用。

#!/usr/local/bin/python
class Study:
        def __init__(self,name=None):
                self.name = name
        def __del__(self):
                print "Iamaway,baby!"
        def say(self):
                print self.name
study = Study("zhuzhengjun")
study.say()

五、理解Self的意义

在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self(可以自定义)。其作用相当于C++中的this指针,表示当前类的对象,可以调用当前类中的属性和方法。
简单的说self就是把 class中定义的变量和函数变成实例变量和实例函数,它和this一样作用域是在类内部,只能在成员函数中使用,使得成员间能互相调用,而不需要从外部调用 数据(即变量)和方法(即函数),以实现数据的封装。
如果不使用self把类中定义的变量和函数实例化,那么在类的成员函数中调用未被实例化的变量或函数便会报错。

self代表类的实例,而非类;self 就是 对象/实例 属性集合

class Box():
    def __init__(self, boxname, size, color):
        self.boxname = boxname
        self.size = size
        self.color = color  # self就是用于存储对象属性的集合,就算没有属性self也是必备的
 
    def open(self, myself):
        print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
        print('-->用类自己的self,打开那个%s,%s的%s' % (self.color, self.size, self.boxname))
 
    def close(self):
        print('-->关闭%s,谢谢' % self.boxname)
 
 
b = Box('魔盒', '14m', '红色')
b.close()
b.open(b)  # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.__dict__)  # 这里返回的就是self本身,self存储属性,没有动作。

在这里插入图片描述

在 class 类的函数中,为什么 self是必要的,因为 self 是对象的载体,可以理解成一个字典,看下面代码:

class Box():
    def myInit(mySelf, boxname, size, color):
        print(mySelf.__dict__)#显示为{}空字典
        mySelf.boxname = boxname
        mySelf.__dict__['aa'] = 'w'#甚至可以像字典一样操作
        mySelf.size = size
        mySelf.color = color  # 自己写一个初始化函数,一样奏效,甚至不用self命名。其它函数当中用标准self
        return mySelf  # 返回给实例化过程一个对象!神奇!并且含有对象属性/字典
 
    # def __init__(self, boxname, size, color):
    #     self.boxname = boxname
    #     self.size = size
    #     self.color = color  #注释掉原来标准的初始化
 
    def open(self, myself):
        print(self)
        print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
        print('-->用类自己的self,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
 
    def close(self):
        print('-->关闭%s,谢谢' % self.boxname)
 
 
# 经过改造,运行结果和标准初始化没区别
 
b = Box().myInit('魔盒', '14m', '红色')
# b = Box('魔盒', '14m', '红色')#注释掉原来标准的初始化方法
b.close()
b.open(b)  # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.__dict__)  # 这里返回的就是self本身,self存储属性,没有动作。

在这里插入图片描述
故可以把 self 理解成存储实例化对象属性的字典(dict), self 存储属性,而没有动作执行.

六、类和函数的注释规范

类的注释规范

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""

函数的注释规范

def func(path, field_storage, temporary):
    '''基本描述

    详细描述

    Args:
        path (str): The path of the file to wrap
        field_storage (FileStorage): The :class:`FileStorage` instance to wrap
        temporary (bool): Whether or not to delete the file when the File instance is destructed

    Returns:
        BufferedFileStorage: A buffered writable file descriptor
    '''
    pass

Python风格规范

七、测试用例

实现名为 Human 的Class,
需要有以下三个方法 ,1、getHeight 返回身高 ,2、getName 返回姓名 3、setName 修改姓名
需要有以下三个属性,1、身高 2、姓名 3、年龄

class Human:		# 定义一个类

    def __init__(self,height,name,age):#类的构造函数,用于初始化类的内部状态,为类的属性设置默认值
        self.height = height	# 定义类的属性
        self.name = name	# 定义类的属性
        self.age = age	# 定义类的属性
    
    def getHeight(self):     # 定义一个类的函数,称为方法,至少含有一个self
        height = self.getHeight
        return height   
    
    def getName(self):     # 定义一个类的函数,称为方法,至少含有一个self
        name = self.name
        return name 
    
    def setName(self,sName):     # 定义一个类的函数,称为方法,至少含有一个self
        self.name = sName   # 修改一个实例变量

t = Human(167,'小王',20)
personName = t.getName()
print(f"名字是:{personName}")
personHeight = t.getHeight()
print(f'身高是:{personHeight}')
t.setName('小李')
personName=t.getName()
print(f"名字是:{personName}")

在这里插入图片描述

1.如果直接返回一个实例变量,是无法打印对应值的,需要定义一个局部变量来作为返回值使用。
2.实例化类的时候不带括号本质上是给类对象起了一个别名,类似C语言中的typedef关键字,而并不会创建一个实例。
3.调用类方法的时候不加括号,调用的是函数(这个对象),不用等函数执行结束;

  • 15
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值