类--python

前言:

python是一种面向对象的语言。面向对象的语言都有类这种数据结构,类有3大特点:继承、封装、多态。

对这些概念不必过多深究,会用了自然知道什么意思。

 

1- 初始 类、对象

语法:

#类的语法

class 类名(父类):
    xxx

#对象语法
对象名 = 类名(入参)

可以把类理解成C语言中的结构体,把对象理解为结构体变量。

 

示例:

下面建立了一个类People,继承的父类为object。

创建了个Mic的方法。

 

【知识点】

__init__:在创建对象时执行

实例方法:类中的一般方法,比如def age、def weight等

私有方法:以__开头的方法,如def __private_func。该函数只能由类内的方法访问。类似于C语言中加了static关键字

类变量:类中方法外边的变量。比如cnt,类变量只能由类名.类变量的方式访问

实例变量:类里面方法中的变量。

私有变量:以__开头的变量。该类型变量只能在类内访问,同私有方法。类似于在变量前加了static关键字

在创建Mic对象时,执行类的__init__接口,就是对象的初始化。

 

import os

class People(object):
    cnt = 0
    def __init__(self, name, age, weight):
        self.name = name
        self.__age = age
        self.__weight=weight
        print("{0} init, self.name:{1}".format(self.__class__, self.name))#self.__class__指向类

    #私有变量访问
    def age(self):
        print("self.__age:{0}".format(self.__age))

    def weitht(self):
        print("self.__weight:{0}".format(self.__weight))

    #访问私有函数
    def __private_func(self):
        print("private func: I have a secret...")

    def call_private_func(self):
        self.__private_func()



Mic = People("kk", 17, 145)
print("cnt:{0}".format(Mic.cnt))
print("name:{0}".format(Mic.name))

#访问私有变量
Mic.age()
Mic.weitht()

#访问私有方法
Mic.call_private_func()

 

 

2- 类方法、静态类方法

和1-定义的方法有所不同,1-定义的实例方法必须创建一个对象后,使用对象名.方法名引用,和对象强相关,且方法的定义格式为def func(self, arg)

类方法不必创建对象,使用类名.类方法名即可引用,由于没有创建对象,所以没有了初始化。格式:必须有@classmethod修饰,def func(cls, arg)。

静态方法和类方法很像,使用类名.静态方法名即可引用。格式:必须有@staticmethod修饰,def func(arg)。这里连cls都省略了。

class 类名(object):
    def __init__(self):
        pass
    @classmethod
    def 类方法名(cls, arg):
        pass
        
    @staticmethod
    def 静态方法名(arg):
        pass

#引用
类名.类方法名(arg)
类名.静态方法名(arg)

 

 

综上:

实例方法引用必须定义对象,且创建对象时会有类的初始化。

而类方法和静态方法的引用不需定义对象,所以可以将一些和对象关系不大的接口定义为类方法或者静态方法。比如我下面写了个计算器的类,里面会有计算器的功能接口,比如加减乘除,可以将这些方法和对象绑定。

还有一些方法可能没必要创建对象再使用(通用的方法),比如查看帮助信息、查看版本号。可以将这些对象定义为类对象或者静态对象,这样直接通过类名就可以查看帮助信息、版本号了,岂不方便。

一句话就是,有些通用接口、和对象关系不大的可以定义为类方法、静态方法,类似于C中的extern修饰的全局函数。

 

示例:

import os

class Calculate(object):
    def __init__(self):
        pass
    @classmethod
    def help(cls):
        print("help info:...")
    @staticmethod
    def get_version():
        print("Calculate version: 0.1")


Calculate.help()
Calculate.get_version()

 

 

3- 类的封装

在类中,有些变量、方法为了安全、内部接口不对外呈现等原因,可以定义为私有变量、私有方法,用法参考1-

对于私有变量、私有方法访问比较麻烦,只能在类内进行访问。如果调试,需要在外面访问,可以使用访问器访问。

访问器分两个:setter和getter

语法:

@property
def getter的方法名(self):
    pass

@setter的方法名.setter
def setter的方法名(self):
    pass

 

示例:

对于类中的体重、年龄比较隐私,我们设置为私有变量,访问体重和设置体重示例如下:

import os

#初始类和对象
class People(object):
    cnt = 0
    def __init__(self, name, age, weight):
        self.name = name
        self.__age = age
        self.__weight=weight
        print("{0} init, self.name:{1}".format(self.__class__, self.name))#self.__class__指向类

    #使用访问器访问私有变量
    @property
    def weight(self):
        return self.__weight

    @weight.setter
    def weight(self, weight):
        self.__weight = weight





Mic = People("kk", 17, 145)

#访问器访问私有变量
print("Mic's weight: {0}".format(Mic.weight))

#访问器设置私有变量
Mic.weight = 135
print("Mic's weight: {0}".format(Mic.weight))

 

4- 类的继承

可以把事物共性的部分封装成父类(基类),事物特有的部分封装成子类。

共有的变量、方法放在父类中,子类特有的变量、方法放在子类中。

 

初识类的继承

以例子说明。有个基类People,包含变量name,age

有个子类Student,继承自父类People。包含变量name、age、grade。

当我们创建一个对象student时,对于name、age这两个变量父类、子类都有,我们在初始化时使用super().__init__(父类、子类共有的变量),将这些父类子类共有的变量放到父类中去初始化。调用链为:子类__init__->父类__init__。

对于父类和子类共有的方法,如果子类由就用子类的,如果子类没有就用父类的,这叫做类的重写。比如Student和People都有借口who_am_i,当子类调用该接口时,打印子类该接口的内容。

import os

#初始类和对象
class People(object):
    cnt = 0
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("class People init")
        print("{0} init".format(self.__class__))  # self.__class__指向类

    def who_am_i(self):
        print("i am people")

class Student(People):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

    def who_am_i(self):
        print("i am Student")

student = Student("kk", 15, 9)
print("name:{0}; age:{1}; grade:{2}".format(student.name, student.age, student.grade))
student.who_am_i()

 

类的多重继承

当一个子类继承自多个父类时,有继承顺序,按照顺序继承。

比如下面的Boy类,继承自父类Student和Worker,创建Boy的对象boy。当boy调用who_am_i时,由于Boy类中没有,需要继承自父类Student和Worker。

顺序是,先去Student中找,如果有则返回,没有采取Worker中找。

import os

#初始类和对象
class People(object):
    cnt = 0
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("class People init")
        print("{0} init".format(self.__class__))  # self.__class__指向类

    def who_am_i(self):
        print("i am people")

class Student(People):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

    def who_am_i(self):
        print("i am Student")

class Worker(People):
    def who_am_i(self):
        print("i am worker")

class Boy(Student, Worker):
    def __init__(self, name, age, grade, sex):
        super().__init__(name, age, grade)
        self.sex = sex


boy = Boy("kk", 15, 9, "boy")
boy.who_am_i()

 

 

5- 类的多态

类的多态在:继承+重写

 

用例子说话:

创建了基类People,两个子类Worker和Student,都继承自父类People。

创建3个对象:people、worker、student,worker和student会继承父类的公共变量。当worker和student调用who_am_i接口时将发生重写父类接口,调用各自类中的接口,这就是多态。

也就是Student和Worker虽然都继承自People,且这三个类都有同样的方法who_am_i,但是各自示例调用这个接口时,却只去自己的类中查找,这就是多态

 

import os

#初始类和对象
class People(object):
    cnt = 0
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def who_am_i(self):
        print("i am people")

class Student(People):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

    def who_am_i(self):
        print("i am Student")

class Worker(People):
    def __init__(self, name, age, work):
        super().__init__(name, age)
        self.work = work

    def who_am_i(self):
        print("i am worker")

people = People("hh", 15)
people.who_am_i()

student = Student("hh", 15, 9)
student.who_am_i()

student = Worker("hh", 15, "IT")
student.who_am_i()

 

类型检查:

接口:

isinstance(对象名,类名)    检查是否是类的对象

issubclass(类名1, 类名2)   检查类名1是否是类名2的子类

import os

#初始类和对象
class People(object):
    cnt = 0
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def who_am_i(self):
        print("i am people")

class Student(People):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

    def who_am_i(self):
        print("i am Student")

class Worker(People):
    def __init__(self, name, age, work):
        super().__init__(name, age)
        self.work = work

    def who_am_i(self):
        print("i am worker")

people = People("hh", 15)
people.who_am_i()

student = Student("hh", 15, 9)
student.who_am_i()

student = Worker("hh", 15, "IT")
student.who_am_i()

print("{0} is object of {1}: {2}".format("student", "People", isinstance(student, People)))
print("{0} is object of {1}: {2}".format("student", "Worker", isinstance(student, Worker)))
print("{0} is object of {1}: {2}".format("people", "People", isinstance(people, People)))

print("{0} is {1} subclass:{2}".format("Student", "Worker", isinstance(Student, Worker)))
print("{0} is {1} subclass:{2}".format("Student", "People", isinstance(Student, People)))

 

鸭子类型

鸭子类型就是个概念,就是说一个事物有鸭子的特征,就可以叫做鸭子。

例子说话:

Animal、Dog、Cat、Car都有run方法,我们不关注类的特征(是否是动物),只关注是否有run方法。

这样做有什么好处呢?通过下面的例子我只理解到一点:虽然Car和其他的类不同,但是都有相同名称的方法,我们可以把相同的接口调用封装起来,这样就做到了和类的隔离(二次封装),是否是这样?

import os

#父类:Animal
class Animal(object):
    def run(self):
        print("animal run...")

#子类:Dog
class Dog(Animal):
    def run(self):
        print("dog run...")

#子类:Cat
class Cat(Animal):
    def run(self):
        print("cat run...")

#子类:Cat
class Car(Animal):
    def run(self):
        print("car run...")

def go(animal):
    animal.run()

go(Animal())
go(Dog())
go(Car())

 

 

6- python根类-object

python的根类为object,我们创建的类都继承自根类object。

object有很多方法,这里简单介绍下__str__和__eq__。

__str__:执行print时,会调用__str__,我们可以定制化打印类

__eq__:执行==时会调用__eq__,我们可以定制化对象相等的条件。

import os

class People(object):
    cnt = 0
    def __init__(self, name, age):
        self.name = name
        self.age = age
    #print函数会调用__self__接口
    def __str__(self):
        print("i am re-write print func")
        template = 'Person [ name={0}, age={1} ]'
        s = template.format(self.name, self.age)
        return s
    #==运算符会调用__eq__接口
    def __eq__(self, other):
        if self.name == other.name and self.age == other.age :
            return True
        else:
            return False


python = People("python", 15)
print(python)

Python = People("python", 15)
print(python == Python)

 

 

7-  枚举类

和c一样python也有枚举类型。

 

初始枚举类型:

这里我们可以把枚举变量的值可以为非整数,且枚举类中的两个变量值可以一样。如果我们想要使枚举类的值为整数、枚举类中变量值不一样,可以使用限制型枚举类

import os
import enum

class WeekDays(enum.Enum):
    MONDAY = 1
    TUESDAY = 2
    WEDNESDAY = 3
    THURSDAY = 4
    FRIDAY = 5 #FRIDAY = 5

day = WeekDays.FRIDAY
print(day) #输出 WeekDays.FRIDAY
print(day.value) #输出 5
print(day.name) #输出 FRIDAY

 

限制性枚举类:

import os
import enum
@enum.unique #限制性枚举类

#枚举类的值为整数
class WeekDays(enum.IntEnum):
    MONDAY = 1
    TUESDAY = 2
    WEDNESDAY = 3
    THURSDAY = 4
    FRIDAY = 5 #FRIDAY = 5

day = WeekDays.FRIDAY
print(day) #输出 WeekDays.FRIDAY
print(day.value) #输出 5
print(day.name) #输出 FRIDAY

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值