day14-类和对象

1 类方法和静态方法

类中的方法分为:对象方法,类方法和静态方法。

1.1 对象方法

1.直接声明在类中;
2.有默认参数self;
3.通过对象去调用。

1.2 类方法

1.在声明前添加@classmethod
2.有默认参数cls,调用的时候不需要给cls传参。系统会自动将调用当前类方法的类传给cls;cls最终指向的是一个类,类可以做的事情cls都可以做
3.通过类去调用: 类.类方法()

1.3 静态方法

1.在声明前添加staticmethod
2.没有默认参数
3.通过类去调用:类.静态方法()

1.4 对象方法、类方法和静态方法的选择

1.4.1什么时候使用对象方法:

当实现函数的功能需要用到对象的属性的时候就使用对象方法.

1.4.2什么时候使用类方法:

实现函数的功能不需要对象的属性,但是需要类(类的字段,创建对象等)的时候就使用类方法.

1.4.3什么时候使用静态方法

实现函数的功能既不需要对象的属性,也不需要类的时候,就使用静态方法.

# 创建一个数学类,属性:pi;功能:求两个数的和,和圆的面积
import math
class Math:
    pi=math.pi
    @staticmethod
    def my_sum(num1,num2):
        return num1+num2
    @classmethod
    def circle(cls, r):
        return cls.pi * r ** 2
print(Math.my_sum(2,3))
print(Math.circle(2))


     # 类方法
    @classmethod
    def destroy(cls):
        print('cls:',cls) # cls: <class '__main__.Person'>
        print('人类破坏环境')
        # 可以用cls来创建对象
        p1=cls('小明')
        p1.eat('面包') #  小明在吃面包
        # 可以用cls使用类的字段
        print(cls.num) # 61
        #  可以用cls调用类相关的方法    
# 调用类方法
Person.destroy()

2.私有化

2.1 私有化

在类中,可以通过在属性名前,或者方法名前加__(注意:不能以__结尾),那么这个属性就会变成私有的;私有的属性和方法在类的外部不能使用。

class Person:
    __num=100 # 私有的属性
    def __init__(self):
        self.name='张三'
    def __show_message(self):
        print(Person.__num)
        print('名字:',self.name)

2.2 私有化原理

python中没有真正的私有化,不能从访问权限上控制属性和方法的使用;只是在名字前有__但是没有以__结尾的名字前再加了'_类名',导致不能直接通过原属性和方法名进行访问。

class Dog:
    def __init__(self,name,color):
        self.__name=name
        self.__color=color
dog1=Dog('大黄','黄色')
# print(dog1.__name) # AttributeError
print(dog1.__dict__) # {'_Dog__name': '大黄', '_Dog__color': '黄色'} 
#私有化的属性可以直接通过dict访问
print(dog1._Dog__name) # 大黄  ,私有化的属性通过_类名__属性名可以访问

3 对象属性的getter和setter

3.1getter和setter

如果希望在获取对象属性之前要做点儿别的事情,就给这个属性添加getter;
如果希望在给对象属性赋值之前做点儿别的事情,就给这个属性添加setter.

3.2给对象属性添加getter

1.属性命名的时候,属性名前加一个_
2.声明一个函数,函数的名字是属性名(不要下划线),不需要参数,有返回值;并且函数前使用@property修饰;这个函数的返回值就是获取属性的结果。

@property
def age(self):
    return 年龄相关值

3.当需要获取属性的时候,通过对象.不带下划线的属性。例如:对象.age

3.3给对象属性添加setter

想要给对象属性添加setter,必须先给它添加getter
1.属性命名的时候,属性名前加_;例如self._age=0
2.声明一个函数,函数的名字是属性名(不要下划线),需要一个额外的参数,不用返回值;
并且函数前使用@getter名.setter修饰

@age.setter
def age(self,value)
    self._age=value

3.当需要给属性赋值的时候,通过对象.不带下划线的属性来赋值;例如:对象.age=100

class Person:
    def __init__(self,name='小红'):
        self.name=name
        self._age=0
        self.sex='男'
    # 这儿的age函数就是属性_age的getter方法
    @property
    def age(self):
        if self._age<1:
            return '婴儿'
        elif self._age<18:
            return '未成年'
        elif self._age<50:
            return '中年'
        else:
            return '老年'
# 这儿的age函数就是属性_age的setter
@age.setter
def age(self,value):
    if not isinstance(value,int):
        print('年龄必须是整数')
        raise ValueError
    if not 0<=value<=100:
        print('年龄超出范围')
        raise ValueError
    self._age=value

补充:打印自己声明的类的对象的时候,默认打印的是:<模块名.类名 object at 对象地址>;如果不希望以默认的方式去打印对象,可以实现__repr__魔法方法。打印对象的时候就会打印这个方法的返回值;这个函数的返回值必须是字符串。

class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __repr__(self):
        # return 'name:%s,age:%d'%(self.name,self.age)
        return str(self.__dict__)[1:-1] 
# 对字典转换来的字符串切片去掉两边的大括号
stu1=Student('小明',29)
stu2=Student('小花',18)
print(stu1,stu2)

4 类的继承

4.1继承

python中的类支持继承,并且支持多继承
python中默认情况是继承自object(object是python中所有类的基类)
1.什么是继承
一个类可以继承另外一个类,继承者我们叫子类,被继承者叫父类。继承就是让子类直接拥有父类中的内容。
2.可以继承哪些内容
所有的属性和方法都可以继承
注意:__slots__魔法对应的值不会被继承

5 添加方法

子类除了拥有从父类继承下来的属性和方法,还拥有属于自己的属性和方法。

5.1在子类中添加方法

5.1.1添加一个新的方法

直接在子类中声明其他的方法;
添加后子类可以拥有自己的方法也可以调用父类的方法,但是父类不能调用子类的方法.

5.1.2重写父类的方法 : 重新实现父类的方法

1.完全重写 - 覆盖父类的功能 - 直接在子类中重新实现父类的方法;
2.部分重写 - 保留父类的功能,添加新的功能 - 在子类中实现父类方法的时候通过super()去调用父类的方法,再添加新的功能。
注意:
1.可以子类的方法中通过super()去调用父类的方法
super(类, 对象) - 获取对象中父类的部分(要求对象是这个指定的类的对象)
2.静态方法中不能使用super()

5.2类中方法的调用过程

1.通过对象或者类调用方法的时候,先看当前类中是否声明过这个方法,如果声明过就直接调用当前类对应的方法;
2.如果当前类中没有声明过,会去找父类中有没有声明过这个方法,声明过就调用父类的方法;
3.如果父类中也没有声明过,就去找父类的父类...以此类推,直到object中也没有声明过,程序才会崩溃。

    # 完全重写,函数名与父类 的一样,都是声明在相同的
    #对象方法/静态方法/类方法中
    @ staticmethod
    def info(cls):
        print('我是学生')
    #  保留父类的功能
    def show_message(self):
        super().show_message()
        print('我去上学')
        super().fun1()

6 添加属性

6.1添加类的字段

直接在子类中添加新的字段

6.2添加对象属性

类的对象属性是通过继承父类的init方法继承下来的。
如果想要在保留父类继承下来的对象属性的前提下,添加新的对象属性,需要在子类的init方法中,通过super()去调用父类的init方法。

练习:1.声明一个动物类,有属性:年龄,颜色,类型。
2.要求创建动物对象的时候类型和颜色必须赋值,年龄可以赋值也可以不赋值。
3.声明一个猫类,有属性:年龄,颜色,类型, 爱好
4.要求创建猫对象的时候,颜色必须赋值,年龄和爱好可以赋值也可以不赋值,类型不能赋值

class Animal: # 创建动物类
    def __init__(self,color,type,age=1):
        self.color=color
        self.type=type
        self.age = age
class Cat(Animal): # 创建猫类
    def __init__(self,color,age=5,hobby='鱼'):
        super().__init__(color,'猫科',age)
        self.hobby=hobby
cat1=Cat('白色') # 创建对象
print(cat1.type,cat1.hobby,cat1.age,cat1.color) # 猫科 鱼 5 白色

7init、call、new及del方法的使用

init主要用于创建对象时进行初始化操作,会自动调用
new方法是类准备在将自身实例化时调用,是一个静态方法,new(cls, *args, *kwargs):cls是当前正在实例化的类,args, **kwargs是实例化传入的参数,new方法在实例化开始之后,init方法调用之前被调用。
call()方法能够让类的实例对象,像函数一样被调用;
del()是类的析构函数,是python垃圾回收机制的实际应用,当类的所有引用都被删除后,该类就会被系统从内存中删除,注意是所有的引用都被删除,而不是每一次删除;

class Student:
    def __init__(self,name ,age):
        self.name = name
        self.age = age
        print('创建对象成功')
    def __del__(self):
        print('对象已经被删除')
    def __call__(self, na):
        print('调用call方法','姓名:%s'% na)
    def __new__(cls, *args, **kwargs):
        print('new方法')
        return super(Student,cls).__new__(cls)        
stu = Student('鲁班', 18)('李白')

输出依次为:new方法;创建对象成功;调用call方法 姓名:李白;对象已经被删除

class Student:
    def __init__(self,name ,age):
        self.name = name
        self.age = age
        print('创建对象成功')
    def __del__(self):
        print('对象已经被删除')
    def __call__(self, *args, **kwargs):
        print('调用call方法')
    def __new__(cls, *args, **kwargs):
        print('new方法')
        return super(Student,cls).__new__(cls)        
stu = Student('鲁班', 18)
print(stu.name)

输出依次为:new方法;创建对象成功;鲁班;对象已经被删除
可以从上面看出当不在对象后面加()并传参时,call函数不被调用,只有传参了才会被调用;new方法最先被调用;del方法一直都是在对象不被使用后才执行。
当在对象后面加()并传参时,stu = Student('鲁班', 18)('李白'),类中的魔法方法它都会执行,执行完后,它就不在是一个对象,而是一个函数;创建对象不管成功与否,都会执行new方法和del方法,即使错误的使用对象(使用没有该属性的属性)造成程序崩溃,依然会在最后执行del方法。

8单下划线和双下划线属性的区别

"单下划线" 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量;"双下划线" 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。
以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用“from xxx import *”而导入;以双下划线开头的(__foo)代表类的私有成员;

class Foo:
    def __init__(self):
        pass
    def public_method(self):
        print ('This is public method')
    def __fullprivate_method(self):
        print ('This is double underscore leading method')
    def _halfprivate_method(self):
        print ('This is one underscore leading method')

f = Foo()
f.public_method()  # ok
f._halfprivate_method()  # ok
f.__fullprivate_method() # error
f._Foo__fullprivate_method() #ok

从上面的例子可以看出,f._halfprivate_method()可以直接访问;不过根据python的约定,应该将其视作private,而尽量不要在外部使用它们。f.__fullprivate_method()不能对其进行访问,__fullprivate_method()是私有方法;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • 1.类方法和静态方法 类中的方法分为:对象方法,类方法,静态方法 1.对象方法 a.直接声明在类中b.有默认参数s...
    发家致富靠养猪阅读 589评论 0 2
  • 1.类中的方法 类中的方法分为:对象方法、类方法、静态方法 1.对象方法 a.直接声明在类中 b.有默认参数sel...
    遇见那天的雨真大阅读 254评论 0 0
  • 记忆里,家里曾养过猪,猪圈就在离家不远的屋后。爸爸种了许多番薯,我们长年累月地吃着番薯,而猪则吃番薯叶,蕃薯藤连着...
    温州老丹阅读 260评论 0 2
  • 风儿轻轻的吹 □晓晨花露 风而轻轻地吹, 阳光温柔地撒在校园里, 校园里留下了先生轻盈的足迹, 日复一日地推着装盘...
    朝花夕拾杯中酒123阅读 283评论 1 6
  • 最近两天天气比较鬼其实下雨这件事情我已经吐槽滚过无数次了所以我今天再说一次...然而天气跟我今天要说的主题又有什么...
    城管队长阅读 352评论 0 0