Python入门示例系列38 面向对象(高级)

 

实例⽅法
    定义:第⼀个参数必须是实例对象,该参数名⼀般约定为“self”,通过它来传递实例的属性和⽅法(也可以传类的属性和⽅法);
    调⽤:只能由实例对象调⽤。
类⽅法
    定义:使⽤装饰器@classmethod。第⼀个参数必须是当前类对象,该参数名⼀般约定为“cls”,通过它来传递的属性和⽅法(不能传实例的属性和⽅法);
    调⽤:实例对象类对象都可以调⽤。
静态⽅法
    定义:使⽤装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是⽅法体中不能使⽤类或实例的任何属性和⽅法;
    调⽤:实例对象类对象都可以调⽤。

 

实例方法,静态方法,类方法 的比较

class Foo:
    """类三种方法语法形式"""

    def instance_method(self):
        print("是类{}的实例方法,只能被实例对象调用".format(Foo))

    @staticmethod
    def static_method():
        print("是静态方法")

    @classmethod
    def class_method(cls):
        print("是类方法")

foo = Foo()
foo.instance_method() # 实例
foo.static_method() # 实例
foo.class_method() # 实例
print('----------------')
Foo.static_method() # 类
Foo.class_method() # 类

说明:

实例方法只能被实例对象调用(Python3 中,如果类调用实例方法,需要显示的传self, 也就是实例对象自己)。

静态方法(由@staticmethod装饰的方法)、类方法(由@classmethod装饰的方法),可以被类或类的实例对象调用。
实例方法,第一个参数必须要默认传实例对象,一般习惯用self
静态方法,参数没有要求。
类方法,第一个参数必须要默认传类,一般习惯用cls

 

class MyClass(object):
 
    def get_info(self, a, b):  # 定义实例方法,有 self 参数
        print("实例方法", a + b)
 
    @classmethod
    def get_other(cls, a, b):  # 定义实例方法,有 cls 参数
        print("类方法", a + b)
 
    @staticmethod
    def get_my_class(a, b):  # 定义静态方法,无默认参数
        print("静态方法", a + b)
 
 
class ExampleClass(object):
    def func(self):
        # 实例化
 
        # 调用实例方法
        MyClass().get_info(1, 6)  # 实例方法
        MyClass.get_info('', 1, 6)  # 实例方法
 
        # 调用类方法,建议通过 类对象.类方法([实参]) 方法调用
        MyClass.get_other(1, 6)  # 类方法
        MyClass().get_other(1, 6)  # 类方法
 
        # 调用静态方法,建议通过 类对象.类方法([实参]) 方法调用
        MyClass.get_my_class(1, 6)  # 静态方法
        MyClass().get_my_class(1, 6)  # 静态方法
 
 
if __name__ == '__main__':
    obj = ExampleClass()
    obj.func()
 
    print("*" * 100)
 
    obj2 = ExampleClass
    obj2.func(1)  
# https://blog.csdn.net/weixin_44799217/article/details/132093785

 

 

类方法用在模拟 java 定义多个构造函数的情况。 由于Python类中只能有一个初始化方法,不能按照不同的情况初始化类

class Book(object):

    def __init__(self, title): # 初始化方法
        self.title = title

    @classmethod
    def create(cls, title):
        book = cls(title=title)
        return book

book1 = Book("python")
book2 = Book.create("python and django")
print(book1.title)
print(book2.title)

静态方法也可以实现上面功能,但静态方法每次都要写上类的名字,不方便。

 

@classmethod 示例:

class A(object):

    # 属性默认为类属性(可以给直接被类本身调用)
    num = "类属性"

    # 实例化方法(必须实例化类之后才能被调用)
    def func1(self): # self : 表示实例化类后的地址id
        print("func1")
        print(self)

    # 类方法(不需要实例化类就可以被类本身调用)
    @classmethod
    def func2(cls):  # cls : 表示没用被实例化的类本身
        print("func2")
        print(cls)
        print(cls.num)
        cls().func1()

    # 不传递传递默认self参数的方法(该方法也是可以直接被类调用的,但是这样做不标准
    def func3():
        print("func3")
        print(A.num) # 属性是可以直接用类本身调用的
    
# A.func1() 这样调用是会报错:因为func1()调用时需要默认传递实例化类后的地址id参数,如果不实例化类是无法调用的
A.func2()
A.func3()

 

输出结果为:

func2
1
foo

 

看下面的定义的一个时间类: 

class Data_test(object):
    day=0
    month=0
    year=0
    def __init__(self,year=0,month=0,day=0):
        self.day=day
        self.month=month
        self.year=year
 
    def out_date(self):
        print "year :"
        print self.year
        print "month :"
        print self.month
        print "day :"
        print self.day
 
t=Data_test(2016,8,1)
t.out_date()

输出:

year :
2016
month :
8
day :
1

 
符合期望。
 
如果用户输入的是 "2016-8-1" 这样的字符格式,那么就需要调用Date_test 类前做一下处理: 

string_date='2016-8-1'
year,month,day=map(int,string_date.split('-'))
s=Data_test(year,month,day)

 
先把‘2016-8-1’ 分解成 year,month,day 三个变量,然后转成int,再调用Date_test(year,month,day)函数。 也很符合期望。
 
那我可不可以把这个字符串处理的函数放到 Date_test 类当中呢?
 
那么@classmethod 就开始出场了
 

class Data_test2(object):
    day=0
    month=0
    year=0
    def __init__(self,year=0,month=0,day=0):
        self.day=day
        self.month=month
        self.year=year
 
    @classmethod
    def get_date(cls,data_as_string):
        #这里第一个参数是cls, 表示调用当前的类名
        year,month,day=map(int,string_date.split('-'))
        date1=cls(year,month,day)
        #返回的是一个初始化后的类
        return date1
 
    def out_date(self):
        print "year :"
        print self.year
        print "month :"
        print self.month
        print "day :"
        print self.day

 
在Date_test类里面创建一个成员函数, 前面用了@classmethod装饰。 它的作用就是有点像静态类,比静态类不一样的就是它可以传进来一个当前类作为第一个参数。
 
那么如何调用呢? 

r=Data_test2.get_date("2016-8-6")
r.out_date()

输出:

year :
2016
month :
8
day :
1

 


 
这样子等于先调用get_date()对字符串进行出来,然后才使用Data_test的构造函数初始化。
 
这样的好处就是你以后重构类的时候不必要修改构造函数,只需要额外添加你要处理的函数,然后使用装饰符 @classmethod 就可以了。

 

python内部类

在Python中,类是一个特殊的数据类型,用于创建对象。有时,我们希望在类的内部定义另一个类,这种在类内部定义的类被称为内部类。内部类在实现一些特定功能时非常有用,本文将详细介绍Python的内部类的概念、语法和用法。

 

概念

内部类是定义在另一个类的内部的类。与外部类不同,内部类可以直接访问外部类的成员,包括属性和方法,甚至可以访问外部类的私有成员。

 

内部类有以下几个特点:
1. 内部类是外部类的一部分,没有独立的存在。
2. 内部类可以直接访问外部类的所有成员,包括私有成员。
3. 内部类可以访问外部类的实例变量和实例方法。
4. 内部类可以定义在外部类的方法中,也可以定义在外部类的代码块中。

语法

 

定义内部类的语法如下所示:

class 外部类:
    # 外部类的代码
    class 内部类:
        # 内部类的代码
 

示例

 

下面通过一个示例来详细说明内部类的用法。假设我们有一个University类,该类表示大学,具有一个内部类Department,该类表示大学的一个部门。

class University:
    def __init__(self, name):
        self.name = name

    def show_university_name(self):
        print("University Name:", self.name)

    class Department:
        def __init__(self, name):
            self.name = name

        def show_department_name(self):
            print("Department Name:", self.name)
 
 

在上面的示例中,University类具有一个Department内部类。内部类Department可以直接访问外部类University的属性和方法。

# 创建大学对象
university = University("ABC University")

# 创建部门对象
department = university.Department("Computer Science")
department.show_department_name()

# 调用外部类的方法
department_2 = University.Department("Mechanical Engineering")
department_2.show_department_name()

university.show_university_name()
 
 

运行上述代码,将得到以下输出:

Department Name: Computer Science
Department Name: Mechanical Engineering
University Name: ABC University
 
 

从以上代码和输出可以清楚地看出,内部类Department可以直接访问外部类University的属性和方法,并且内部类的对象可以通过外部类名直接创建。

 

总结

内部类是Python中一个非常有用的概念,可以帮助我们实现更灵活和模块化的代码结构。内部类可以直接访问外部类的成员,包括私有成员,并且可以定义在外部类的方法或代码块中。通过合理地使用内部类,我们可以更好地组织和管理代码,并实现更高层次的封装。


 
 

 

 

 

https://geek-docs.com/python/python-ask-answer/119_hk_1707969098.html

 

 

REF:

https://www.jb51.net/article/168278.htm

https://www.cnblogs.com/baxianhua/p/10845620.html

https://zhuanlan.zhihu.com/p/21101992

https://wenku.baidu.com/view/5c2c4a9b8462caaedd3383c4bb4cf7ec4afeb693.html

https://baijiahao.baidu.com/s?id=1700147092491716904&wfr=spider&for=pc

https://www.cnblogs.com/baxianhua/p/10845620.html

https://www.runoob.com/python/python-func-classmethod.html

posted @ 2022-03-23 23:17  emanlee  阅读(117)  评论(0编辑  收藏  举报