python—面向对象(二)

1、新式类和旧式(经典)类
新式类:以object为基类的类
经典类:不以object为基类的类

在python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类–python3.x中定义的类都是新式类

在python2.x中定义类时,如果没有指定父类,则不会以object作为基类

为保证编写的代码能够同时在python2.x和python3.x运行,今后在定义类时,如果没有父类,建议统一继承自object

2、类属性和类方法

类属性:针对类本身定义的属性, 使用赋值语句在class关键字下可以定义类属性,这类属性归类本身所有。使用类名.属性调用类属性

当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到,当实例并没有该属性,所以会继续查找class的该属性

class Animal(object):
    name = 'Animal'    #定义类属性
    def run(self):
        print('animal is running')
print(Animal.name)   # 输出类属性
cat = Animal() # 实例化一个对象
print(cat.name)  # 实例没有name属性,继续访问类属性

#输出结果:
Animal
Animal   

在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为实例属性优先级高于类属性。相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性

class Animal(object):
    name = 'Animal'   # 定义类属性name
    
    def __init__(self,name):
        self.name = name   # 定义实例属性name
    def run(self):
        print('animal is running')
cat = Animal('tom')  # 实例化一个实例
print(cat.name)  # 打印类的name属性,由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
del cat.name #如果删除实例的name属性
print(cat.name) #再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了

类方法:针对类定义的方法 在类方法内部可以直接访问类属性或者调用其他的类方法,直接使用 类名.类方法名称 调用类方法
格式:

@classmethod
def 方法名称(cls):   # cls表示调用该方法的类本身
	操作
class Animal(object):
    name = 'Animal'

    def run(self):
        print('animal is running')

    @classmethod
    def speak(cls):
        print(' %s can speak english' %cls.name)
cat = Animal()
Animal.speak()

#输出结果:
 Animal can speak english

**应用实例:**统计创造的学生对象的数量

class Student(object):
    count = 0
    def __init__(self,name):
        self.name = name
        Student.count += 1
    @classmethod
    def Student_count(cls):
        print(Student.count)

a = Student('tom')
b = Student('xixi')
c = Student('erpang')
Student.Student_count()

#输出结果:
3
3、私有属性和私有方法

私有属性:前面带两个下划线表示对变量进行私有化,私有化之后的属性属于类内部的属性,可以在内部进行访问,为不无法随便进行访问或者修改。

私有方法:方法名称前面带两个下划线表示方法私有化,可以在内部进行调用,不能使用实例在外部调用私有化方法。

定义方法
在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法

class Animal(object):
    def __init__(self,name,color,weight):
        self.name = name
        self.color = color
        self.__weight = weight # 定义私有属性
    def run(self):
        print('animal in running')
    def weight(self):
        print('animal is %s weight' %self.__weight)
    def __speak(self):   #定义私有方法
        print('can speak english')
cat = Animal('tom','blue','35')
print(cat.name)
print(cat.color)
print(cat.__weight)  # 无法直接访问私有属性

#输出结果:
tom
blue
    print(cat.__weight)
AttributeError: 'Animal' object has no attribute '__weight'   # 出现报错
cat = Animal('tom','blue','35')
cat.weight()
cat.run()
cat.__speak()   #外部无法调用该私有方法

#输出结果:
Traceback (most recent call last):
  File "/home/kiosk/PycharmProjects/20190523/6.13/练习7.py", line 21, in <module>
    cat.__speak()     # 出现报错
AttributeError: 'Animal' object has no attribute '__speak'
animal is 35 weight    # 其他方法正常可以被调用
animal in running
4、静态方法

如果需要在类中定义一个方法,这个方法,既不需要访问实例属性也不需要调用实例方法;既不需要访问类属性也不需要调用类方法,这个时候就可以把这个方法封装成静态方法。使用@staticmethod关键字进行设置

格式:

class Cat(object):
    @staticmethod
    def run():
        print('running')

可以直接使用类名.方法名进行调用静态方法

class Cat(object):
    @staticmethod
    def run():
        print('running')

Cat.run()   #直接使用`类名.方法名`进行调用静态方法
tom = Cat()
tom.run()    # 实例化对象,然后通过对象调用静态方法。

#输出结果:
running
running  #两种方法输出一致
5、设计模式——单例
设计模式:

设计模式是前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对某一特定问题的成熟解决方案,使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码可靠性

单例设计模式:

目的:让类创建对象,在系统中只有唯一的一个实例,每一次执行类名()返回的对象,内存地址是相同的

使用__new__(cls)方法实现单例设计模式:

我们用 类名. 的方式创建对象的时候,python解释器会帮我们做两件事情,
1.为对象分配空间

  • __new__是一个由object基类提供的内置的静态方法,主要有两个作用: 在内存中为对象分配空间 返回对象的引用
  • new:负责给对象分配空间,并返回对象的引用给初始化方法

2.对象初始化

  • __init__(初始化方法)负责给对象初始化.
  • 解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法

重点

在Python3中,class定义的时候,如果不显式的写继承object,也是会默认自动继承object的,所以也会有__new__(cls)

也就是说在使用类名创建对象的时候,会自动的调用object基类中的__new__(cls)方法生成对象并返回对象的引用。

我们可以在类中对__new__(cls)方法进行重写,使其达到效果是:如果是第一次使用该类创建对象,那就在内存中为对象分配内存空间,并且返回对象的引用,如果已经创建过对象,那就不在重新分配内存空间,直接返回上依次创建好的内存空间即可。

所以需要一个类属性来记录是否已经创建过对象,以及存储第一次创建对象时分配的内存地址空间。

单例设计模式 示例:

class Dog(object):
    __instance = None  #定义类属性,判断是否第一次创建对象以及记录对象内存地址
    def __new__(cls):   #对父类方法进行重写
        if cls.__instance == None: # None 就表示还没创建过对象
            #调用object父类方法创建对象分配地址以及返回对象引用,由设定的类属性接收
            cls.__instance = object.__new__(cls)
            return cls.__instance # 如果是第一次创建 返回这个创建好的实例对象引用
        else:
            # 不是第一次创建,那么之前创建的对象地址的引用就是在cls.__instance中,直接返回。
            return cls.__instance

多次创建对象,但是其内存地址只有一个:

a = Dog()
b = Dog()
c = Dog()
d = Dog()
print(a)
print(b)
print(c)
print(d)

#输出结果:
<__main__.Dog object at 0x7fa674e9b400>
<__main__.Dog object at 0x7fa674e9b400>
<__main__.Dog object at 0x7fa674e9b400>
<__main__.Dog object at 0x7fa674e9b400>  # 创建的所有的对象均引用同一个内存地址。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值