Python 学习之 --- 语法部分(面向对象)

16 篇文章 0 订阅
13 篇文章 0 订阅


1. 面向对象概述

  在现实世界中存在各种不同形态的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象间的关系来描述事物之间的联系,这种思想就是面向对象。

面向对象技术概念:

  • 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 局部变量:定义在方法中的变量,只作用于当前实例的类。
  • 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
  • 实例化:创建一个类的实例,类的具体对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

2. 类和对象

类和对象的关系:

  • 面向对象编程有两个非常重要的概念:类和对象。
  • 对象是面向对象编程的核心。
  • 具有相似特征和行为的事物的集合统称为类
  • 对象是根据类创建的,一个类可以对应多个对象。

类的定义

类是由 3 部分组成的:

  • 类的名称:首字母必须大写,比如 Person。
  • 类的属性:用于描述事物的特征,比如性别。
  • 类的方法:用于描述事物的行为,比如说话。

使用 class 关键字来声明一个类,基本格式如下:

class 类名:
    类的属性
    类的方法

根据类创建对象:

对象名 = 类名()

给对象添加属性:

对象名.新的属性名 =

示例:

class Person:   #定义一个人类
    role = 'person'  #人的角色属性都是人
    def walk(self):  #人都可以走路,也就是有一个走路方法
        print("person is walking...")


print(Person.role)  #查看人的role属性
print(Person.walk)  #引用人的走路方法,注意,这里不是在调用

# 结果
person
<function Person.walk at 0x000002715B7A7940>

#--------------------------------------------------------
class Employee:
    '所有员工的基类'
    empCount = 0

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1

    def displayCount(self):
        print
        "Total Employee %d" % Employee.empCount

    def displayEmployee(self):
        print
        "Name : ", self.name, ", Salary: ", self.salary
// empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。
// 第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法。
// self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。

#--------------------------------------------------------
class Student(object):
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def student_name(self):
        return 'my name is {}'.format(self.name)

    def student_name(self):
        return 'my age is {}'.format(self.age)

    def student_sex(self):
        return 'i am a {}'.format(self.sex)

new_student = Student('jia', 12, 'boy')
print(new_student.student_name())
new1_student = Student('jia', 12, 'boy')
print(new1_student.student_name())

# 结果
my age is 12
my age is 12

3. 构造方法和析构方法

class Car:
    def __init__(self):
        self.color = "黑色"

    def toot(self):
        print("%s的车在鸣笛..."%(self.color))

#----------------------------------------------
class Student():
    def __init__(self, name, scores):
        # 这里增加了属性name,并将所有成绩作为一个参数scores传入
        # self.name是self的属性,单独的name是函数内的局部变量,参数也是局部变量
        self.name = name
        if len(scores) == 3:
            self.scores = scores
        else:
            self.scores = [0] * 3

stu_1 = Student("Alice", [80, 90, 85])
print(stu_1.name)
print(stu_1.scores)

# 结果
Alice
[80, 90, 85]
  • 当删除一个对象来释放类所占用资源的时候,Python 解释器默认会调用另外一个方法,这个方法就是 __del__( ) 方法。
  • __del__ 方法被称为析构方法。
    http://c.biancheng.net/view/2371.html
class CLanguage:
    def __init__(self):
        print("调用 __init__() 方法构造对象")
    def __del__(self):
        print("调用__del__() 销毁对象,释放其空间")
clangs = CLanguage()
#添加一个引用clangs对象的实例对象
cl = clangs
del clangs
print("***********")

# 结果
调用 __init__() 方法构造对象
***********
调用 __del__() 销毁对象,释放其空间

#---------------------------------------------
class CLanguage:
    def __del__(self):
        print("调用父类 __del__() 方法")

class cl(CLanguage):
    def __del__(self):
        print("调用子类 __del__() 方法")
c = cl()
del c

# 结果
调用子类 __del__() 方法

4. self 的使用

  • 在方法的参数列表中,第 1 个参数永远都是 self。
  • self 的字面意思是自己,我们可以把它当做 C++ 里面的 this 指针理解,表示的是对象自身。
  • 当某个对象调用方法的时候,Python 解释器会把这个对象作为第 1 个参数传给 self,开发者只需要传递后面的参数就可以了。
  • https://zhuanlan.zhihu.com/p/95788606
  • http://c.biancheng.net/view/2266.html
class Dog:
    def __init__(self, new_color):
        self.color = new_color
    def print_color(self):
         print("颜色为:%s"%self.color)

dog_white = Dog("白色")
dog_white.print_color()

# 结果
颜色为:白色

#-------------------------------------
class Person:
    def __init__(self):
        print("正在执行构造方法")
    # 定义一个study()实例方法
    def study(self):
        print(self,"正在学Python")
zhangsan = Person()
zhangsan.study()
lisi = Person()
lisi.study()

# 结果
正在执行构造方法
<__main__.Person object at 0x00000164781D7A60> 正在学Python
正在执行构造方法
<__main__.Person object at 0x0000016478219130> 正在学Python

#--------------------------------------
class Person:
    def __init__(self):
        print("正在执行构造方法")
    # 定义一个study()实例方法
    def study(self):
        print(self,"正在学Python")
zhangsan = Person()
zhangsan.study()
lisi = Person()
lisi.study()

# 结果
zhangsan
lisi

5. 运算符重载

methodoverloadcall
__init__构造函数对象创建: X = Class(args)
__del__析构函数X对象收回
__add__云算法+如果没有_iadd_, X+Y, X+=Y
__or__运算符|如果没有_ior_,X|Y, X|=Y
__repr__, __str__打印,转换print(X),repr(X),str(X)
__call__函数调用X(*args, **kwargs)
__getattr__点号运算X.undefined
__setattr__属性赋值语句X.any=value
__delattr__属性删除del X.any
__getattribute__属性获取X.any
__getitem__索引运算X[key],X[i:j]
__setitem__索引赋值语句X[key],X[i:j]=sequence
__delitem__索引和分片删除del X[key],del X[i:j]
__len__长度len(X),如果没有__bool__,真值测试
__bool__布尔测试bool(X)
__lt__, __gt__, __le__, __ge__, __eq__, __ne__特定的比较X<Y,X>Y,X<=Y,X>=Y, X==Y,X!=Y 注释:(lt: less than, gt: greater than, le: less equal, ge: greater equal, eq: equal, ne: not equal )
__radd__右侧加法other+X
__iadd__实地(增强的)加法X+=Y(or else add)
__iter__, __next__迭代环境I=iter(X), next()
__contains__成员关系测试item in X(任何可迭代)
__index__整数值hex(X), bin(X), oct(X)
__enter__, __exit__环境管理器with obj as var:
__get__, __set__, __delete__描述符属性X.attr, X.attr=value, del X.attr
__new__创建在__init__之前创建对象

常用重载运算符:

加法运算符重载

加法运算是通过调用 __add__ 方法完成重载的,当两个实例对象执行加法运算时,自动调用 __add__ 方法。

z = x + y
// 执行加法运算,实质是调用 __add__ 方法

索引和分片重载

跟索引相关的重载方法包括如下 3 个:

  • __getitem__:索引、分片。

在对实例对象执行索引、分片或者 for 迭代操作时,会自动调用 __getitem__ 方法。

# 重写索引、分片运算符重载方法
def __getitem__(self, index):
    return self.data[index]
  • __setitem__:索引赋值。

通过赋值语句给索引或者分片赋值时,调用 __ setitem __ 方法实现对序列对象的修改。

def __setitem__(self, index, value):
        self.data[index] = value
  • __delitem__:索引和分片删除。

当使用 del 语句时,实质上会调用 __delitem__ 方法实现删除操作。

def __delitem__(self, index):
        del self.data[index]

6. 封装

  在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用。要了解封装,离不开 “私有化”,就是将类或者是函数中的某些属性限制在某个区域之内,外部无法调用。
https://www.cnblogs.com/Michael–chen/p/6740455.html
https://www.jb51.net/article/146383.htm
https://www.cnblogs.com/ostrich-sunshine/p/9415698.html

封装数据的主要原因是:

  保护隐私。(把不想别人知道的东西封装起来)。

封装方法的主要原因是:

  隔离复杂度。(比如:电视机,我们看见的就是一个黑匣子,其实里面有很多电器元件,对于用户来说,我们不需要清楚里面都有些元件,电视机把那些电器元件封装在黑匣子里,提供给用户的只是几个按钮接口,通过按钮就能实现对电视机的操作。)

PS:在编程语言里,对外提供的接口(接口可理解为了一个入口),就是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。

class Person: 
    def __init__(self, name, age): 
        self.name = name 
        self.age = age    
laowang = Person("老王", 30) 
laowang.age = 300
print(laowang.age)
// 人的年龄可以随便设置,显然不可行。

为了保护类里面的属性,可以采用如下方式解决:

  1. 把属性定义为私有属性,即在属性名的前面加上两个下划线。
  2. 添加用于设置或获取属性值的两个方法供外界调用。

下面采用封装的方式,对 Person 类的代码进行修改:

def __init__(self, name, age):
self.name = name # 姓名
self.__age = age # 年龄

def set_age(self, new_age):
	if new_age > 0 and new_age <= 120:
		self.__age = new_age

def get_age(self):
	return self.__age

其他示例:

# 类的设计者
class room:     # 定义一个房间的类
    def __init__(self,name,owner,length,width,high):
        self.name = name
        self.owner = owner
        self.__length = length  # 房间的长
        self.__width = width    # 房间的宽
        self.__high = high      # 房间的高

    @property   # @property 是 python 的一种装饰器,是用来修饰方法的
    def area(self):     # 求房间的平方的功能
        return self.__length * self.__width     # 对外提供的接口,隐藏了内部的实现细节

# 类的使用者(实例化对象通过接口,调用相关属性得到想要的值)
r1 = room("客厅","michael",20,30,9)   # 实例化一个对象 r1
print(r1.area)  # 通过接口使用 (area),使用者得到了客厅的面积

### 结果
600

###-----增加一个求体积功能-----###
# 扩展原有的代码,增加功能
# 类的设计者
class room:     # 定义一个房间的类
    def __init__(self,name,owner,length,width,high):
        self.name = name        # 房间名
        self.owner = owner      # 房子的主人
        self.__length = length  # 房间的长
        self.__width = width    # 房间的宽
        self.__high = high      # 房间的高

    @property   # @property 是 python 的一种装饰器,是用来修饰方法的
    def area(self):     # 对外提供的接口,隐藏内部实现
        return self.__length * self.__width,\
               self.__length * self.__width * self.__high   # 增加了求体积功能
# 内部逻辑变了,只需增加这行代码就能简单实现,而且外部调用感知不到,仍然使用该方法,但是功能已经增加了

# 类的使用者
r1 = room("客厅","michael",20,30,9)   # 实例化一个对象 r1
print(r1.area)  # 通过接口使用 (area),使用者得到了客厅的面积

### 结果
(600, 5400)

7. 继承

概述

  • 在现实生活中,继承一般指的是子女继承父辈的财产。在程序中,继承描述的是事物之间的从属关系。
  • 类的继承是指在一个现有类的基础上构建一个新的类,构建出来的新类被称作子类,现有类被称作父类。
  • 现实生活中,一个派生类往往会有多个基类。比如沙发床是沙发和床的功能的组合,这都是多重继承的体现。
  • Python 支持多继承,多继承就是子类拥有多个父类,并且具有它们共同的特征,即子类继承了父类的方法和属性。
  • 如果子类继承的多个父类间是平行的关系,子类先继承的哪个类就会调用哪个类的方法。
  • 在继承关系中,子类会自动拥有父类定义的方法,但是有时子类想要按照自己的方式实现方法,即对父类中继承来的方法进行重写,使得子类中的方法覆盖掉跟父类同名的方法。需要注意的是,在子类中重写的方法要和父类被重写的方法具有相同的方法名和参数列表。

单继承:class 子类名(父类名)
多继承:class 子类名(父类名1,父类名2…)

https://www.cnblogs.com/bigberg/p/7182741.html
https://zhuanlan.zhihu.com/p/30239694

示例

单继承

class Father(object):       # 定义一个父类
    def fa(self):           # 父类中的方法
        print("这是父类的输出")

class Son(Father):          # 定义一个子类,继承 Father 类
    def so(selfs):          # 在子类中定义其自身的方法
        print("这是子类的输出")

c = Son()
c.fa()    # 调用继承父类的 Person 类的方法
c.so()    # 调用本身的方法

## 结果
这是父类的输出
这是子类的输出

多继承

class Item:
    def info(self):
        print("Item 父类中的方法")

class Product:
    def info(self):
        print("Product 父类中的方法")

class Computer(Item,Product):
    pass

c = Computer()
c.info()		# Item 父类中的方法
# 当以一个子类有多个直接父类时,该子类会继承得到所有父类的方法。
# 但是如果其中有多个父类包含同名方法会发生什么?
# 此时排在前面的父类中的方法会 "遮蔽" 后面父类中的方法。

#------------------------------------------------------------#
class Item:
    def it(self):
        print("Item 父类中的方法")

class Product:
    def pr(self):
        print("Product 父类中的方法")

class Computer(Item,Product):
    def so(selfs):
        print("这是子类的输出")

c = Computer()
c.it()
c.pr()
c.so()

# 结果
Item 父类中的方法
Product 父类中的方法
这是子类的输出

构造函数的继承

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.weight = 'weight'

    def talk(self):
        print("person is talking ......")

class Chinese(Person):
    def __init__(self, name, age, language):    # 先继承,再重构
        Person.__init__(self, name, age)        # 继承父类的构造方法,也可以写成:super(Chinese,self).__init__(name,age)
        self.language = language                # 定义类的本身属性

    def walk(self):
        print("chinese is walking ......")

class American(Person):
    pass

c = Chinese('bigberg', 22, 'chinese')

# 如果我们只是简单的在子类 Chinese 中定义一个构造函数,其实就是在重构。
# 这样子类就不能继承父类的属性了。所以我们在定义子类的构造函数时,要先继承再构造,才获取父类的属性。

子类对父类方法的重写

# 如果我们对父类的方法需要修改,可以在子类中重构该方法。如下的 talk() 方法。
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.weight = 'weight'

    def talk(self):
        print("person is talking...")

class Chinese(Person):
    def __init__(self, name, age, language):
        Person.__init__(self, name, age)
        self.language = language
        print(self.name, self.age, self.weight, self.language)

    def talk(self):  # 子类重构方法
        print('%s is speaking chinese' %self.name)

    def walk(self):
        print('chinese is walking...')

c = Chinese('bigberg', 22, 'Chinese')
c.talk()

# 结果
bigberg 22 weight Chinese
bigberg is speaking chinese

类继承的实例

class SchoolMember(object):
    '''学习成员基类'''
    member = 0

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

    def enroll(self):
        '注册'
        print('just enrolled a new school member [%s].' % self.name)
        SchoolMember.member += 1

    def tell(self):
        print('----%s----' % self.name)
        for k, v in self.__dict__.items():
            print(k, v)
        print('----end-----')

    def __del__(self):
        print('开除了[%s]' % self.name)
        SchoolMember.member -= 1


class Teacher(SchoolMember):
    '教师'

    def __init__(self, name, age, sex, salary, course):
        SchoolMember.__init__(self, name, age, sex)
        self.salary = salary
        self.course = course

    def teaching(self):
        print('Teacher [%s] is teaching [%s]' % (self.name, self.course))


class Student(SchoolMember):
    '学生'

    def __init__(self, name, age, sex, course, tuition):
        SchoolMember.__init__(self, name, age, sex)
        self.course = course
        self.tuition = tuition
        self.amount = 0

    def pay_tuition(self, amount):
        print('student [%s] has just paied [%s]' % (self.name, amount))
        self.amount += amount


t1 = Teacher('Wusir', 28, 'M', 3000, 'python')
t1.tell()
s1 = Student('haitao', 38, 'M', 'python', 30000)
s1.tell()
s2 = Student('lichuang', 12, 'M', 'python', 11000)
print(SchoolMember.member)
del s2

print(SchoolMember.member)

8. 多态

  在强类型语言(例如 Java 或 C#)中,多态指允许使用一个父类类型的变量或常量来引用一个子类类型的对象。Python 中多态指在不考虑对象类型的情况下使用对象。
https://www.cnblogs.com/feeland/p/4419121.html

相比于强类型,Python 更推崇 “鸭子类型”。“鸭子类型” 是这样推断的:如果一只生物走起路来像鸭子,游起泳来像鸭子,叫起来也像鸭子,那么它就可以被当做鸭子。也就是说,它不关注对象的类型,而是关注对象具有的行为。

示例一

class A(object):
    def test(self):
        print("A--test")

class B(A):
    def test(self):
        print("B--test")

def func(temp):
    temp.test()

a = A()
b = B()
func(a)
func(b)

# 结果
A--test
B--test

// 对象 a、b 分别调用 func 函数的结果不一样,这体现了多态。

示例二

class Person(object):
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex

    def print_title(self):
        if self.sex == "male":
            print("man")
        elif self.sex == "female":
            print("woman")

class Child(Person):                # Child 继承 Person
    def print_title(self):
        if self.sex == "male":
            print("boy")
        elif self.sex == "female":
            print("girl")

May = Child("May","female")
Peter = Person("Peter","male")

print(May.name,May.sex,Peter.name,Peter.sex)
May.print_title()
Peter.print_title()
  • 当子类和父类都存在相同的 print_title()方法时,子类的 print_title() 覆盖了父类的 print_title(),在代码运行时,会调用子类的 print_title()。这样,我们就获得了继承的另一个好处:多态。
  • 多态的好处就是,当我们需要传入更多的子类,例如新增 Teenagers、Grownups 等时,我们只需要继承 Person 类型就可以了,而 print_title() 方法既可以直不重写(即使用 Person 的),也可以重写一个特有的。这就是多态的意思。调用方只管调用,不管细节,而当我们新增一种 Person 的子类时,只要确保新方法编写正确,而不用管原来的代码。这就是著名的 开闭 原则:
  • 对扩展开放(Open for extension):允许子类重写方法函数
  • 对修改封闭(Closed for modification):不重写,直接继承父类方法函数

9. 类属性和实例属性

  • 属性就是属于一个对象的数据或者函数,我们可以通过句点 . 来访问属性,同时 python 还支持在运作中添加和修改属性。
  • 数据变量类似于 name = 'scolia' 这样的形式会称其为字段。而类里面的函数又称为方法。而方法又分为 实例方法类方法静态方法
  • 类属性:就是类对象所拥有的属性,它被所有类对象的实例对象所共有,类对象和实例对象可以访问。
  • 实例属性:实例对象所拥有的属性,只能通过实例对象访问。

https://blog.csdn.net/qq_39457296/article/details/108000982
https://www.jb51.net/article/226154.htm

示例一

class Student:
    name='黎明' 			#属于类属性 就是 Student 类对象所拥有的
    def __init__(self,age):
        self.age=age 	#实例属性
        pass
    pass
lm=Student(17)
print(lm.name)   		#通过实例对象去访问类属性
print(lm.age)

## 结果
黎明
17

示例二

class Student:
    name='黎明' 			#属于类属性 就是 Student 类对象所拥有的
    def __init__(self,age):
        self.age=age 	#实例属性
        pass
    pass
lm=Student(17)
print(lm.name)   		#通过实例对象访问类属性
print(Student.name)		#通过类对象访问类属性

## 结果
黎明
黎明

示例三:对类属性进行修改

class Student:
    name='黎明'			#属于类属性,就是 Student 类对象所拥有的
    def __init__(self,age):
        self.age=age    #实例属性
        pass
    pass
Student.name='赵丽颖'	#类属性此时已被修改
lm=Student(17)
print(lm.name)          #通过实例对象去访问类属性
lm.name='李嘉欣'       	#通过实例对象对类属性进行修改,不可以,并未被修改
print(lm.name)      	#追加新的属性,对于下方调用仍未修改
print(lm.age)
print('------小花的数据---------')
xh=Student(28)
print(xh.name)  		#name 还是黎明
print(xh.age)
print('-------------通过类对象访问 name-------------')
print(Student.name)

## 结果
赵丽颖
李嘉欣
17
------小花的数据---------
赵丽颖
28
-------------通过类对象访问 name-------------
赵丽颖

10. 实例方法(instance method),类方法(class method)与静态方法(static method)

https://blog.csdn.net/lihao21/article/details/79762681
https://www.cnblogs.com/yunxiaofei/p/11210240.html

10.1 实例方法

  • Python 的实例方法用得最多,也最常见。
class Kls(object):
    def __init__(self, data):
        self.data = data

    def printd(self):
        print(self.data)

ik1 = Kls('leo')
ik2 = Kls('lee')

ik1.printd()
ik2.printd()

## 结果
leo
lee

printd 为一个实例方法。实例方法第一个参数为 self,当使用 ik1.printd() 调用实例方法时,实例 ik1 会传递给 self 参数,这样 self 参数就可以引用当前正在调用实例方法的实例。利用实例方法的这个特性,上述代码正确输出了两个实例的成员数据。

10.2 类方法

  • Python 的类方法采用装饰器 @classmethod 来定义。
class Kls(object):
    num_inst = 0

    def __init__(self):
        Kls.num_inst = Kls.num_inst + 1

    @classmethod
    def get_no_of_instance(cls):
        return cls.num_inst

ik1 = Kls()
ik2 = Kls()

print(ik1.get_no_of_instance())
print(Kls.get_no_of_instance())

## 结果
2
2

在上述例子中,我们需要统计类 Kls 实例的个数,因此定义了一个类变量 num_inst 来存放实例个数。通过装饰器 @classmethod 的使用,方法 get_no_of_instance 被定义成一个类方法。在调用类方法时,Python 会将类 class Kls 传递给 cls,这样在 get_no_of_instance 内部就可以引用类变量 num_inst由于在调用类方法时,只需要将类型本身传递给类方法,因此既可以通过类也可以通过实例来调用类方法

10.3 静态方法

  • 在开发中,我们常常需要定义一些方法,这些方法跟类有关,但在实现时并不需要引用类或者实例。例如:设置环境变量,修改另一个类的变量等。这个时候,我们可以使用静态方法。
  • Python 使用装饰器 @staticmethod 来定义一个静态方法。
IND = 'ON'

class Kls(object):
    def __init__(self, data):
        self.data = data

    @staticmethod
    def checkind():
        return IND == 'ON'

    def do_reset(self):
        if self.checkind():
            print('Reset done for: %s' % self.data)

    def set_db(self):
        if self.checkind():
            print('DB connection made for: %s' % self.data)

ik1 = Kls(24)
ik1.do_reset()
ik1.set_db()

## 结果
Reset done for: 24
DB connection made for: 24

在代码中,我们定义了一个全局变量 IND,由于 IND 跟类 Kls 相关,所以我们将方法 checkind 放置在类 Kls 中定义。方法 checkind 只需检查 IND 的值,而不需要引用类或者实例,因此,我们将方法 checkind 定义为静态方法。对于静态方法,Python 并不需要传递类或者实例,因此,既可以使用类也可以使用实例来调用静态方法

10.4 实例方法,类方法与静态方法的区别

注意下述代码中方法 foo,class_foo,static_foo 的定义以及使用。

class Kls(object):
    def foo(self, x):
        print('executing foo(%s,%s)' % (self, x))

    @classmethod
    def class_foo(cls,x):
        print('executing class_foo(%s,%s)' % (cls,x))

    @staticmethod
    def static_foo(x):
        print('executing static_foo(%s)' % x)


ik = Kls()

# 实例方法
ik.foo(1)
print(ik.foo)
print('==========================================')

# 类方法
ik.class_foo(1)
Kls.class_foo(1)
print(ik.class_foo)
print('==========================================')

# 静态方法
ik.static_foo(1)
Kls.static_foo('hi')
print(ik.static_foo)

结果

executing foo(<__main__.Kls object at 0x0000022663377610>,1)
<bound method Kls.foo of <__main__.Kls object at 0x0000022663377610>>
==========================================
executing class_foo(<class '__main__.Kls'>,1)
executing class_foo(<class '__main__.Kls'>,1)
<bound method Kls.class_foo of <class '__main__.Kls'>>
==========================================
executing static_foo(1)
executing static_foo(hi)
<function Kls.static_foo at 0x00000226633B7CA0>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值