微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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。

 

方法用在模拟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 就可以了。

 

 

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐