面向对象--中

一、特殊方法

  • 在类中可以定义一些特殊特殊方法
    • 完成特殊方法需要保证的三点
      • 1.在类中,name对我我们的程序是必须的
      • 2.但是,name又都是不同的
      • 3.在设置好name之后手动添加属性又融基忘记
  • 特殊方法的形式
    • 语法:
__名称__()

这种方式的方法就是特殊方法,又称为魔法方法。

  • 特殊方法不需要我们调用,特殊方法会在特定的时间自动调用。
  • 特殊方法演示示例:
    1.普通的类:
class Person:
    # 在类的内部创建一个方法(speak是方法名)
    def speak(self):
        print('你好我是%s' % self.name)


# 创建对象(实例)
p1 = Person()
p1.name = '刘德华'
p2 = Person()
p2.name = '张家辉'
p1.speak()
p2.speak()

打印输出结果:

你好我是刘德华
你好我是张家辉

2.特殊方法类:

class Person:
    # 类属性:
    # name = '向华强'
    def __init__(self,name): # 新建init方法 # self就是实例(对象),通过类似函数穿参的模式,将name传入实参
        self.name = name

    # print('类中的print') # 通过总结2可知,本行代码如果运行,将是最先运行的代码。
    def speak(self): # 新建speak方法
        print('大家好,我是%s' % self.name)


p1 = Person('刘德华') # 本行代码中的刘德华,就像函数穿参的中的实参。通过函数函数穿参的模式,传递给33行代码中的name,函数再继续向下执行,通过38行代码进行拼接,打印输出。
# 调用init方法
# p1.__init__() # 通过总结1可知本行代码属于二次调用,非需要时,不写。
p2 = Person('郭富城')
p3 = Person('何润东')
p1.speak()
p2.speak()
p3.speak()

打印输出结果:

大家好,我是刘德华
大家好,我是郭富城
大家好,我是何润东

总结:

  • 1.每创建一个实例对象,解释器python就会调用一次init魔法方法。
  • 2.在面向对象的函数中,类是最大的,执行顺序也是优先执行的。

二、封装的引入

  • 封装的基本概念
    • 封装是面向对象的三大特征之一。
    • 封装出现的原因:
      • 1.属性不能随意修改
      • 2.属性不能改为任意的值
    • 封装是指隐藏对象中一些不希望被外部所访问的属性和方法。
    • 我们可以提供一个getter()方法和setter()方法是外部可以访问已经封装的属性。
      • getter()方法用来获取对象中指定的属性
      • setter()方法用来设置对象指定的属性
    • 封装的思想:
      • 1.我们需要一种方式来增强数据的安全性。
      • 2.属性不能随意更改。(允许修改时,才能修改。)
      • 3.属性不能为任意值。
    • 可以为对象的属性使用双下划线开头__xxx。双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部访问,无法通过对象访问。
    • 其实隐藏属性只不过是python自动为属性改了一个名字——>_累名__属性名,例如__name ——>_Person__name(这种方式实际上依然可以在外部访问,但是这种方式我们一般不用。一般我们会将一些私有属性以单下划线开头)
    • 一般来说,单下划线开头的属性都是私有实行,没有特殊情况下不要修改私有属性。
      封装思想的简单演示:
class Car:
    def __init__(self, name, color):
        self.name = name
        self.color = color

    def run(self):
        print('汽车开始跑了')

    def horn(self):
        print('BIBIBIBIKBI')


car = Car('法拉利','红色')
# print(car.name, car.color)
car.name = '小猫咪'
print(car.name,car.color)
car.run()
car.horn()

打印输出结果:

汽车开始跑了
BIBIBIBIKBI

分析:上述代码应该输出
小猫咪 红色
汽车开始跑了
BIBIBIBIKBI

但是为car实例添加的属性为小猫咪时,小猫咪的这恶搞属性就覆盖了法拉利。
这样就打乱了这一类的代码。导致错误。

三、封装

  • 封装其实是做出一个相对封装的效果。(所谓古语曰:防君子不防小人)
  • 封装演示实例:

1、比较low的封装

class Dog:
    def __init__(self, name):
        self.hidden_name = name


dog = Dog('哈士奇')
# print(dog.hidden_name)
dog.name = '田园犬'
print(dog.hidden_name)

打印输出结果:
哈士奇
分析:使用这种方式过于简单,只是简单的对哈士奇进行了封装,田园犬这个属性没有对哈士奇这个属性产生影响。

2、封装实例演示:

class Dog:
    def __init__(self, name):
        self.hidden_name = name

    # getter()--查看属性方法:(可读)
    def getter_name(self):
        print('用户调用了此读取方法')
        return self.hidden_name

    # setter()--修改属性方法:(可写)
    def setter_name(self, name):
        print('用户调用了此修改方法')
        self.hidden_name = name

dog = Dog('哈士奇')
dog.setter_name('田园犬')
print(dog.getter_name())

打印输出结果:

用户调用了此修改方法
用户调用了此读取方法
田园犬

分析:首先,在代码内部定义出了读取方法和修改方法,就证明,该代码内部的封装属性是可以修改的。
总结: 封装确实增加了类的定义的负责程度,但是也保证了数据的安全。

  • 1.隐藏属性名,使调用者无法随意的修改对象中的属性。
  • 2.增加了getter()方法和setter()方法,很好控制属性是否是只读的。
  • 3.使用setter()方法设置属性,可以在再做一个数据的验证。
  • 4.使用getter()方法获取属性,使用setter()方法设置属性可以读取属性和修改属性的同时做一些其他的处理。

3、真正意义上的封装

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

    # getter()--查看属性方法:(可读)
    def getter_name(self):
        print('用户调用了此读取方法')
        return self._name

    # setter()--修改属性方法:(可写)
    def setter_name(self, name):
        print('用户调用了此修改方法')
        self._name = name


p1 = Person('陈慧翎')
p1.setter_name('周慧敏')
# print(p1._name) # 未调用get方法禁止查看属性
# p1.name = '黄一琳'
# print(p1.name)
print(p1.getter_name())

打印输出结果:

用户调用了此修改方法
用户调用了此读取方法
周慧敏

总结:
__name的意思是禁止修改此属性(相当于加了一层).

四、property装饰器

  • property装饰器
  • 我们可以适应@property装饰器来创建只读属性,@property装饰器会将方法转换为相同名称的制只读属性,可以与虽定义的属性配合使用,这样可以防止属性被修改。
    演示示例:
class Person:
    def __init__(self, name):
        self._name = name

    @property # 设置只读属性(与getter方法类似)
    def name(self):
        print('getter方法执行了')
        return self._name

    @name.setter # 代表setter方法
    def name(self, name):
        print('setter方法执行了')
        self._name = name


p1 = Person('周慧敏')
p1.name = '黄一琳'
print(p1.name)

打印输出结果:
setter方法执行了
getter方法执行了
黄一琳

总结:首先通过装饰器设置只读属性,再通过装饰器设置setter可修改属性,就可以告诉其他的同事,这是一个封装的参数,如果需要修改请通过正当方式修改。

五、PEP8代码书写规范

  • 缩进使用4个空格,空格是首选的缩进方式,python3不允许混合使用制表符和空格来缩进。
  • 每一行最大长度限制在79个字符以内。
  • 顶层函数、类的定义。前后使用两个空行隔开。
  • import导入
    • 建议在不同的行导入,例如
import os
omport sys

也可以这样:

from subprocess import Popen, PIPE
  • 导包位于文件顶部,在模块注释、文档字符串之后,全局变量、常量之前,导入按照以下顺序分组:
    标准库导入
    相关第三方库导入
    本地应用/库导入
    在每一组导入之间加入空行
  • python中定义字符串使用双引号、单引号是相同的,尽量保持使用同一方式定义字符串,当一个字符串包包含单引号或者双引号时,在做外层使用不同的符号来避免使用反斜杠转译,从而提高可读性。
  • 百搭是个语句中的空格:
    1.避免在小括号、方括号、花括号后跟空格。
    2.避免在都好、分号、冒号之前添加空格。
    3.冒号在切片中就像二元运算符,两边要有相同数量的空格,如果某个切片参数省略,空格也省略。
    4.避免为了和另外一个赋值语句对齐,在赋值运算符附加多个空格。
    5.避免在表达式尾部添加空格,因为表达式尾部空格通常看不见,会产生混乱。
    6.总是在二元运算符两边加一个空格,赋值(=),增量赋值(+=,-=),比较(==,<,>,!=,<>,<=,>=,in,not,in,is.is not),布尔(and,偶然,not)
    7.避免将小的代码和if/for/while放在同一行,要避免代码太长。
 1 if foo == 'blah': do_blah_thing()
 2 for x in lst: total += x
 3 while t < 10: t = delay()
  • 永远不要使用字母’l’(L),o(O)或者大写的I作为字符串的变量,在有些字体里这些字符无法和数字0和1区分。
  • 累名一般使用首字母大写的约定。
  • 函数名应该小写,如果想提高可读性可以用下划线分割
  • 如果函数的参数名和已有的关键词冲突,在做后加单一下划线比缩写或者随意拼写更好。
  • 方法名和实例变量使用下划线分隔的小写单词,以提高可读性。

猜你喜欢

转载自blog.csdn.net/Rhymeplot__JDQS/article/details/109132569