OOP -面向对象

  • 1.python的面向对象相关概念
  • 2.类与对象
    • 2.1 类和对象的创建
    • 2.2 类属性与实例属性
    • 2.3 类方法和实例方法
    • 2.4 self
  • 3.面向对象编程
    • 封装
    • 继承
    • 构造init()函数,super
    • 单继承和多继承
    • 多态
    • 组合,Minxi
  • 4.类相关函数
  • 5.类的成员描述符
  • 6.魔法函数
    • 魔法函数概述
    • 够造类魔法函数
    • 运算类魔法函数

一、面向对象概述(objectOriented)

  • OOP思想

    • 接触到任意一个任务,首先想到的是任务这个世界的构成,是由模型构成的
  • 几个名词
    • OO:面向对象
    • OOA:面向对象的分析(任务这个世界由哪些对象组成)
    • OOD:面向对象的设计(其中每个对象由哪些属性和方法)
    • OOI:xxx的实现
    • OOP:xxx的编程
    • OOA -> OOD -> OOI:面向对象的实现过程

二、类和对象的概念

  • 类:抽象名词,代表一个有共性事物的集合,
  • 对象:具体的事物,单个个体
  • 类和对象的关系
    • 一个具象,代表一类事物的某一个个体
    • 一个是抽象,代表的是一大类事物
  • 类中的内容,应该具有两个内容
    • 表明事物的特征,叫做属性(变量)
    • 表明事物的功能或动作,叫做成员方法(函数)

2.1、类的基本实现

  • 类的命名

    • 遵守变量命名的规范
    • 大驼峰:由一个或多个单词构成,每个单词首字母大写,单词跟单词直接相连
    • 尽量避开跟系统命名相似的命名
  • 类的声明
    • 必须用class关键字
    • 类由属性和方法构成,其他不允许出现
    • 成员属性定义可以直接使用变量赋值,如果没有值,允许使用None
  • 实例化类 变量 = 类名() #实例化了一个对象
  • 访问对象成员
    • 使用点操作符 obj.成员属性 obj.成员方法
  • 可以通过默认内置变量检查类和对象的所有成员
    • 对象所有成员检查 obj.dict
    • 类所有的成员 class_name.dict
# 定义一个学生类,用来形容学生# 定义一个空的类
class Student():pass# 定义一个对象
Jason = Student()# 定义一个类,用来描述听Python的学生
class PythonStudent():name = Noneage = 18course = "Python"# 需要注意# 1. def doHomework的缩进层级# 2. 系统默认有一个self参数def doHomework(self):print("Doing homework")return None# 实例化一个叫liu的学生,是一个具体的人
liu = PythonStudent()
print(liu.name)# 注意成员函数的调用没有传递进入参数
liu.doHomework()
None
Doing homework
# 类变量,不属于具体的某个对象,属于A类的
class A():name = "jason"age = 18A.__dict__a = A()
print(a.name)
jason

2.2、类和实例的成员分析

  • 类和实例都可以存储成员,成员可以归类所有,也可以归实例所有
  • 类存储成员时使用的是与类关联的一个实例
  • 实例存储成员是存储在当前实例中
  • 实例访问一个成员时,如果实例中没有该成员,尝试访问类中的同名成员,如果实例中有此成员,一定使用实例中的成员
  • 创建实例的时候,类中的成员不会放入实例当中,而是得到一个空实例,没有成员
  • 通过实例对类中成员重新赋值或者通过实例添加成员时,对应成员会保存在实例中,而不会修改类成员
  • 访问或调用类变量的正确方式是类名.变量名或者self.class.变量名
class A():name = "jason"age = 18def say(self):self.name = "aaa"self.age = 200# 类对象的属性和实例对象的实例的属性在不对对象的实例属性赋值的前提下,执行同一个变量# A称为类实例
print(A.name)
print(A.age)print("*" * 20)print(id(A.name))
print(id(A.age))print("*" * 20)a = A()
print(a.name)
print(a.age)
print(id(a.name))
print(id(a.age))
jason
18
********************
4563031520
4526644384
********************
jason
18
4563031520
4526644384
class A():name = "jason"age = 18def say(self):self.name = "aaa"self.age = 200def __init__(self, name):self.name = nameprint(id(A.name))a = A("tony9")
print(id(a.name))
a.name = "tony"
print(id(a.name))
4427228696
4427229872
4427228472
# A称为类实例
print(A.name)
print(A.age)print("*" * 20)print(id(A.name))
print(id(A.age))print("*" * 20)
a = A()print(A.__dict__)
print(a.__dict__)a.name = "liu"
a.age = 16print(a.__dict__)print(a.name)
print(a.age)
print(id(a.name))
print(id(a.age))
jason
18
********************
4563031520
4526644384
********************
{'__module__': '__main__', 'name': 'jason', 'age': 18, 'say': <function A.say at 0x10ffb2620>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
{}
{'name': 'liu', 'age': 16}
liu
16
4563032192
4526644320

2.3、类方法

  • 属于类的方法不使用self参数, 而使用参数cls,代表类本身
  • 另外习惯上对类方法我们会加上@classmethod的修饰符做说明
# 类方法案例1
from time import time, localtime, sleepclass Clock(object):def __init__(self, hour=0, minute=0, second=0):self._hour = hourself._minute = minuteself._second = second@classmethoddef now(cls):ctime = localtime(time())return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)def run(self):self._second += 1if self._second == 60:self._second = 0self._minute += 1if self._minute == 60:self._minute = 0self._hour += 1if self._hour == 24:self._hour = 0def show(self):"""显示时间"""return '%02d:%02d:%02d' % (self._hour, self._minute, self._second)def main():# 通过类方法创建对象并获取系统时间clock = Clock.now()while True:print(clock.show())sleep(1)clock.run()if __name__ == '__main__':main()
08:59:38
08:59:39
08:59:40
08:59:41
08:59:42
08:59:43
08:59:44
08:59:45
08:59:46
08:59:47
08:59:48
08:59:49

2.4、关于self

  • self在对象的方法中表示当前对象本身,如果通过对象调用一个方法,那么该对象会自动传入到当前方法的第一个参数中
  • self并不是关键字,只是一个用于接收对象的普通参数,理论上可以用任何一个普通变量名代替
  • 方法中有self形参的方法成为非绑定类的方法,可以通过对象访问,没有self的是绑定类的方法,只能通过类访问
  • 使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过class 前后两个下划线
# self案例,self并不是关键字
class Student():name = "jason"age = 18def say(self):self.name = "aaa"self.age = 200print("My name is {0}".format(self.name))print("My age is {0}".format(self.age))def sayagain(s):print("My name is {0}".format(s.name))print("My age is {0}".format(s.age))
stu = Student()
stu.say()
stu.sayagain()
My name is aaa
My age is 200
My name is aaa
My age is 200
# 案例class Student():name = "jason"age = 18def say(self):self.name = "aaa"self.age = 200print("My name is {0}".format(self.name))print("My age is {0}".format(self.age))print("class age is {0}".format(__class__.age))def sayagain():print(__class__.name)print(__class__.age)print("hello")stu = Student()
stu.say()
stu.sayagain()
Student.sayagain()
My name is aaa
My age is 200
class age is 18---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-4-e1a607ea9759> in <module>19 stu = Student()20 stu.say()
---> 21 stu.sayagain()22 Student.sayagain()TypeError: sayagain() takes 0 positional arguments but 1 was given
# 关于self的案例,以下代码,利用了鸭子模型class A():name = "jasonliu"age = 18def __init__(self):self.name = "tonyliu"self.age = 200def say(self):print(self.name)print(self.age)class B():name = "bbb"age = 90a = A()
# 此时,系统会默认把a作为第一个参数传入函数
a.say()# 此时,self被a替换
A.say(a)# 同样可以把A作为参数传入
A.say(A)# 此时,传入的是类实例B,因为B具有name和age属性,所以不会报错
A.say(B)
tonyliu
200
tonyliu
200
jasonliu
18
bbb
90

三、面向对象的三大特性

3.1、封装

  • 封装就是对对象的成员进行访问限制;一般都是向外部类提供一些按钮来对其内部的成员进行访问,以保证程序的安全性

    • 封装的三个特性:

      • 公开:public
      • 受保护的:protected
      • 私有的: private
      • public private protected 不是关键字,主要是一种思想
  • 区分方法
    • 类内部
    • 类外部
    • 子类中
  • private
    • 私有是最高级别的封装,只能在当前类或对象中访问
    • 在成员属性前面添加两个下划线就代表是私有
    • Python的私有不是真私有,是一种成为name mangling的改名策略,可以使用对象._classname__attributename访问
  • protected
    • 受保护的封装是将对象成员进行一定级别的封装,然后在类中或者子类中都可以进行访问
    • 封装方法:在成员名称前添加一格下划线即可
    • 是一种约定的规范,而不是语言层面真的实现了访问控制,所以,我们定义的保护变量,依然可以在外部被访问到
  • public
    • 公共的封装实际对成员没有任何操作,任何地方都可以访问
# 封装案例1,实例属性
class Student():def __init__(self, name):self.__name = nameself._age = 18def get_name(self):print("My name is {0}".format(self.__name))class low_student(Student):def get_age(self):print("My age is {0}".format(self._age))liu = Student("liucheng")
#print(liu.name)
print(liu._Student__name)
#print(liu.age)
print(liu._age)
liu.get_name()
han = low_student("liuxiang")
han.get_age()
liucheng
18
My name is liucheng
My age is 18
# 封装案例2,类属性
class Student1():name = "jason"__age = 18_schole = "shanghai"def get_age(self):print("My name is {0}".format(self.__age))s = Student1()
print(s.name)print(s._Student1__age)
print(s._schole)
s._schole = "beijing"
print(s._schole)
print(Student1._schole)
s.name = "tony"
print(s.name)
print(Student1.name)
jason
18
shanghai
beijing
shanghai
tony
jason

3.2、继承

  • 继承就是一个类可以获得另一个类中的成员属性和成员方法
  • 作用:减少代码,增加代码的复用性,同时可以设置类与类之间的关系
  • 继承与被继承的概念:
    • 父类是被继承的类,也叫基类
    • 用于继承的类是子类,也叫派生类
    • 继承与被继承一定存在一个is-a关系
  • 继承的语法
  • 继承的特征:
    • 所有类都继承自object
    • 子类一旦继承父类,则可以使用父类中除私有成员外的所有内容
    • 子类继承父类后并没有将父类成员完全赋值到子类中,而是通过引用关系访问调用
    • 子类中可以定义独有的成员属性和方法
    • 子类中定义的成员和父类如果相同,则优先使用子类成员
    • 子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员来进行代码重用,可以使用父类名.父类成员的格式来调用父类成员,也可以使用super().父类成员的格式调用
  • 继承变量函数的查找顺序问题
    • 优先查找自己的变量
    • 没有查找父类
    • 构造函数如果本类中没有定义,则自动查找调用父类构造函数
    • 构造函数如果本类有定义,则不在继续向上查找
# 继承语法
# 在Python中,任何类都有一个共同的父类叫objectclass Person():name = "NoName"age = 0__score = 0 # 考试成绩是秘密,只要自己知道_petname = "sec" #小名,是保护的,子类可以用,但不能公用def sleep(self):print("sleeping ...")# 父类写在括号内
class Teacher(Person):teacher_id = "9527"def make_test(self):print("attention")t = Teacher()
print(t.name)
print(Teacher.name)print(t._petname)# 公开访问私有变量会报错
#print(t.__score)t.sleep()
print(t.teacher_id)
t.make_test()
NoName
NoName
sec
sleeping ...
9527
attention
# 子类扩充父类的方法
class Person():name = "NoName"age = 0__score = 0 # 考试成绩是秘密,只要自己知道_petname = "sec" #小名,是保护的,子类可以用,但不能公用def sleep(self):print("sleeping ...")def work(self):print("make some money")# 父类写在括号内
class Teacher(Person):teacher_id = "9527"def make_test(self):print("attention")def work(self):#Person.work(self)super().work()self.make_test()t = Teacher()
t.work()
make some money
attention
class SchoolMember:def __init__(self, name, age):self.name = nameself.age = agedef tell(self):# 打印个人信息print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ")class Teacher(SchoolMember):def __init__(self, name, age, salary):SchoolMember.__init__(self, name, age) # 利用父类进行初始化self.salary = salary# 方法重写def tell(self):SchoolMember.tell(self)  # super().tell() print('Salary: {}'.format(self.salary))

3.3、构造函数

  • 是一类特殊的函数,在类进行实例化之前进行调用
  • 如果定义了构造函数,则实例化时使用构造函数,不查找父类构造函数
  • 如果没有定义,则自动查找父类构造函数
  • 如果子类没定义,父类的构造函数带参数,则构造对象时的参数应该按父类参数构造
  • 当多继承时
    • 按顺序继承,哪个父类在最前面且它又有自己的构造函数,就继承它的构造函数;
    • 如果最前面第一个父类没有构造函数,则继承第2个的构造函数,第2个没有的话,再往后找,以此类推
class Dog():# 每次实例化的时候,第一个被调用# 因为主要工作是进行初始化,所以得名def __init__(self):print("I am init in dog")kaka = Dog()
I am init in dog
# 继承中的构造函数 -1
class Animal():passclass PaxingAni(Animal):passclass Dog(PaxingAni):def __init__(self):print("I am init in dog")# 实例化的时候,括号内的参数需要跟构造函数参数匹配
kaka = Dog()
I am init in dog
# 继承中的构造函数 -2
class Animal():passclass PaxingAni(Animal):def __init__(self):print("Paxing dongwu")class Dog(PaxingAni):def __init__(self):print("I am init in dog")# 实例化的时候,括号内的参数需要跟构造函数参数匹配
# 因为找到了构造函数,则不再查找父类的构造函数
kaka = Dog()class Cat(PaxingAni):pass# 此时应该自动调用构造函数,因为Cat没有构造函数,所以查找父类的构造函数
# 在PaxinAni中查找到了
c = Cat()
I am init in dog
Paxing dongwu
# 继承中的构造函数 -3
class Animal():def __init__(self):print("Animal")class PaxingAni(Animal):def __init__(self, name):print("Paxing dongwu {0}".format(name))class Dog(PaxingAni):def __init__(self):print("I am init in dog")# 实例化Dog时,查找到Dog的构造函数,参数匹配,不报错
d = Dog()class Cat(PaxingAni):pass# 此时,由于Cat没有构造函数,则向上查找
# 因为PaxingAni的构造函数需要两个参数,实例化的时候给了一个,报错
c = Cat()
I am init in dog---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-51-7ccb365305f0> in <module>20 # 此时,由于Cat没有构造函数,则向上查找21 # 因为PaxingAni的构造函数需要两个参数,实例化的时候给了一个,报错
---> 22 c = Cat()TypeError: __init__() missing 1 required positional argument: 'name'
# 继承中的构造函数 -4
class Animal():def __init__(self):print("Animal")class PaxingAni(Animal):passclass Dog(PaxingAni):passd = Dog()class Cat(PaxingAni):passc = Cat()
Animal
Animal

3.3、super

  • super不是关键字,而是一个类
  • super的作用是获取MRO(Method Resolution Order) 列表中的第一个类
  • super于父类之间没有任何实质性关系,但通过super可以调用到父类
  • super使用两个方法,参见在构造函数中调用父类的构造函数
class A():passclass B(A):passclass C(B, A):passprint(A.__mro__)
print(B.__mro__)
(<class '__main__.A'>, <class 'object'>)
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

3.4、单继承和多继承

  • 单继承:每个类只能继承一个类
  • 多继承:每个类允许多个类
  • 单继承和多继承的优缺点
    • 单继承:

      • 传承有序 逻辑清晰 语法简单 隐患少
      • 功能不能无限扩展,只能在当前唯一继承链中扩展
    • 多继承:
      • 优点:类的功能扩展方便
      • 缺点:继承关系混乱
  • 菱形继承/钻石继承问题
    • 多个子类继承自同一个父类,这些子类又被同一个类继承,于是继承关系图形成一个菱形图谱
    • 关于多继承的MRO
      • MRO就是多继承中,用于保存继承顺序的一个列表

        • (, , , )
      • Python本身采用C3算法来多多继承的菱形继承进行计算的结果
      • MRO列表的计算原则:
        • 子类永远在父类前面
        • 如果多个子类,则根据继承语法中括号内类的书写顺序存放
        • 如果多个继承了同一个父类,则子类中只会取继承语法括号中第一个父类的父类
      • mro方法搜索顺序
        • 是按照 mro 的输出结果 从左至右 的顺序查找的
        • 在当前类中 找到方法,就直接执行,不再搜索
        • 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
        • 找到最后一个类,还没有找到方法,程序报错
  • Mixin设计模式:
    • 主要采用多继承方式对类的功能进行扩展
    • Mixin概念
      • 表示混入(mix-in),mixin类是作为功能添加到子类中,而不是作为父类
    • MRO and Mixin
    • Mixin模式
    • Mixin MRO
    • MRO
  • 我们使用多继承语法来实现Mixin
  • 使用Mixin实现多继承的时候非常小心
    • 首先他必须表示单一功能,而不是某个物品
    • 职责必须单一,如果由多个功能,则写多个Mixin
    • Mixin不能依赖于子类的实现
    • 最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。
# 多继承的例子
# 子类可以直接拥有父类的属性和方法,私有属性和方法除外
class Fish():def __init__(self, name):self.name = namedef swim(self):print("i am swimming....")class Bird():def __init__(self, name):self.name = namedef fly(self):print("i am flying....")class Person():def __init__(self, name):self.name = namedef workd(self):print("Working.......")class SuperMan(Person, Bird, Fish):def __init__(self, name):self.name = names = SuperMan("jason")
s.fly()
s.swim()# 单继承的例子
class Student(Person):def __init__(self, name):self.name = namestu = Student('jason')
stu.workd()
i am flying....
i am swimming....
Working.......
# 菱形继承问题
class A():passclass B(A):passclass C(A):passclass D(B, C):pass
# Mixin案例
class Vehicle(object):passclass PlaneMixin(object):def fly(self):print('I am flying')class Airplane(Vehicle, PlaneMixin):pass
class Displayer():def display(self, message):print(message)class LoggerMixin():def log(self, message, filename='logfile.txt'):with open(filename, 'a') as fh:fh.write(message)def display(self, message):super().display(message)self.log(message)class MySubClass(LoggerMixin, Displayer):def log(self, message):super().log(message, filename='subclasslog.txt')subclass = MySubClass()
print(MySubClass.__mro__)
#subclass.display("This string will be shown and logged in subclasslog.txt")
(<class '__main__.MySubClass'>, <class '__main__.LoggerMixin'>, <class '__main__.Displayer'>, <class 'object'>)

3.5、多态

  • 同一个对象在不同情况下有不同的状态出现
  • 多态不是语法,是一种设计思想
  • 多态性:一种调用方式,不同的执行效果
    • 向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)
    • 一个接口,多种实现
  • 多态:同一事物的多种形态,动物可以有猫,狗,猪
# 多态案例
from abc import ABCMeta, abstractmethodclass Pet(object, metaclass=ABCMeta):"""宠物"""def __init__(self, nickname):self._nickname = nickname@abstractmethoddef make_voice(self):"""发出声音"""passclass Dog(Pet):"""狗"""def make_voice(self):print('%s: 汪汪汪...' % self._nickname)class Cat(Pet):"""猫"""def make_voice(self):print('%s: 喵...喵...' % self._nickname)def main():pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]for pet in pets:pet.make_voice()if __name__ == '__main__':main()
旺财: 汪汪汪...
凯蒂: 喵...喵...
大黄: 汪汪汪...

四、类相关函数

- 检测一个类是否是一个类的子类- issubclass
- 检测一个对象是否是对象实例- isinstance
- 检测一个对象是否有成员xxx- hasattr- getattr- setattr- delattr

类的内置属性

- __dict__:以字典的方式显示类的成员组成
- __doct__:获取类的文档属性
- __name__:获取类的名称,如果在模块中使用,获取模块的名称
- __bases__:获取类的所有父类,以元组的形式展现

五、类的成员描述符(属性)

  • 类的成员描述符是为了在类中对类的成员属性进行相关操作而创建的一种方式(托管属性)

    • 好处

      • 保护属性不受修改
      • 属性类型检查和自动更新某个依赖属性的值
    • 方法
      • __get__(self, instance, owner) :用于访问属性。它返回属性的值,或者在所请求的属性不存在的情况下出现 AttributeError 异常
      • __set__(self, instance, value):将在属性分配操作中调用。不会返回任何内容
      • __delete__(self, instance):控制删除操作。不会返回内容
  • 如果想使用类的成员描述符,大概有三种方法
    • 使用类实现描述器
    • 使用属性修饰符
    • 使用property函数
      • property函数语法
      • property(fget, fset, fdel, doc)
  • 无论哪种修饰符都是为了对成员属性进行相应的控制
    • 类的方式:适合多个类中的多个属性共用一个描述符
    • property:在当前类中使用,可以控制一个类中多个属性
    • 属性修饰符:在当前类中使用,控制一个类中的一个属性
# 创建Student类,描述学生类,学生具有Student.name属性,但name格式并不统一
class Student():def __init__(self, name, age):self.name = nameself.age = ageself.setName(name)def intro(self):print("hi, my name is {0}".format(self.name))# 方法1 增加setName方法def setName(self, name):self.name = name.upper()s1 = Student("LIU Jason", 19)
s2 = Student("tony liu", 20)
s1.intro()
s2.intro()
hi, my name is LIU JASON
hi, my name is TONY LIU
# property函数案例
# 定义一个Person类,具有name, age属性
# 对于任意输入的姓名,我们希望都用大写方式保存
# 年龄,我们希望内部统一用整数保存class Person():def fget(self):return self._name * 2def fset(self, name):self._name = name.upper()def fdel(self):self._name = "NoName"name = property(fget, fset, fdel, "对name进行操作")p1 = Person()
p1.name = "test"
print(p1.name)
TESTTEST
# 将 property 函数用作装饰器class Person():def __init__(self):self._name = None@propertydef name(self):return self._name@name.setterdef name(self, name):self._name = name@name.deleterdef name(self):del self._namep2 = Person()
#p2.name = "jason"
print(p2.name)
None
# 类方法案例1
from time import time, localtime, sleepclass Clock(object):def __init__(self, hour=0, minute=0, second=0):self._hour = hourself._minute = minuteself._second = second@classmethoddef now(cls):ctime = localtime(time())return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)def run(self):self._second += 1if self._second == 60:

类的常用魔术方法

  • 参考:https://pycoders-weekly-chinese.readthedocs.io/en/latest/issue6/a-guide-to-pythons-magic-methods.html
  • 魔术方法就是不需要人为调用的方法,基本是在特定的时刻自动触发
  • 魔术方法的统一的特征:方法名被前后各两个下划线包裹
  • 操作类
    • init()
    • new():
    • call(): 对象当函数使用的时候触发
    • str(): 当对象被当做字符串使用的时候在调用
    • repr: 返回字符串,和str具体区别
  • 描述符相关
    • set
    • get
    • delete
  • 属性操作相关
    • getattr
    • setattr

类和对象的三种方法

  • 实例方法

    • 需要实例化对象才能使用的方法
  • 静态方法
    • 不需要实例化,通过类直接方法
  • 类方法
    • 不需要实例化
# 静态方法案例1
from math import sqrtclass Triangle(object):def __init__(self, a, b, c):self._a = aself._b = bself._c = c@staticmethoddef is_valid(a, b, c):return a + b > c and b + c > a and a + c > bdef perimeter(self):return self._a + self._b + self._cdef area(self):half = self.perimeter() / 2return sqrt(half * (half - self._a) *(half - self._b) * (half - self._c))if __name__ == "__main__":a, b, c = 3, 4, 5if Triangle.is_valid(a, b, c):t = Triangle(a, b, c)print(t.perimeter())print(t.area())else:print('无法构成三角形.')
12
6.0
# 自定义静态方法案例2
from math import sqrtclass myStaticObject(object):def __init__(self, fun):self.fun = fundef __get__(self, instance, owner):print('call myStaticObject __get__')return self.fundef my_static_method(fun):return myStaticObject(fun)class Triangle(object):def __init__(self, a, b, c):self._a = aself._b = bself._c = c@my_static_methoddef is_valid(a, b, c):return a + b > c and b + c > a and a + c > bdef perimeter(self):return self._a + self._b + self._cdef area(self):half = self.perimeter() / 2return sqrt(half * (half - self._a) *(half - self._b) * (half - self._c))if __name__ == "__main__":a, b, c = 3, 4, 5if Triangle.is_valid(a, b, c):t = Triangle(a, b, c)print(t.perimeter())print(t.area())else:print('无法构成三角形.')
call myStaticObject __get__
12
6.0
# 类方法案例1
from time import time, localtime, sleepclass Clock(object):def __init__(self, hour=0, minute=0, second=0):self._hour = hourself._minute = minuteself._second = second@classmethoddef now(cls):ctime = localtime(time())return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)def run(self):self._second += 1if self._second == 60:
File "<ipython-input-55-4d7c40e59cb2>", line 17if self._second == 60:^
SyntaxError: unexpected EOF while parsing

python 对象_python面向对象相关推荐

  1. python对象_Python对象()

    python对象 Python object() function returns a new featureless object. Python is an object-oriented pro ...

  2. python中如何创建类的对象_python面向对象中如何建立具体的对象?

    我们现在眼前所能看到的事物,都是具体的对象.很多小伙伴在面向对象中创建对象,其实都停留在对象名称的建立,计算机中并没有具体对象的描述属性.我们想要使用python中的类,建立的对象就需要是具体的.下面 ...

  3. python 对象_Python小课堂面向对象

    Python3 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. 如果你以前没有接触 ...

  4. python的类和对象_Python面向对象之类和对象实例详解

    本文实例讲述了Python面向对象之类和对象.分享给大家供大家参考,具体如下: 类和对象(1) 对象是什么? 对象=属性(静态)+方法(动态): 属性一般是一个个变量:方法是一个个函数: #类的属性 ...

  5. python多态_Python面向对象教程之多态

    今天给大家介绍面向对象最后一个重要的特性--多态.如果想温习前两个重要特性(继承和封装),可以点开:<Python面向对象教程之基本概念>.<Python面向对象教程之单继承> ...

  6. python 封装_Python 面向对象三大特性之封装

    封装 定义:隐藏对象的属性和实现细节,仅对外提供公共访问方式. [好处] 将变化隔离: 便于使用: 提高复用性: 提高安全性: [封装原则] 将不需要对外提供的内容都隐藏起来: 把属性都隐藏,提供公共 ...

  7. python 对象_Python中的Barrier对象

    python中的Barrier对象用于等待固定数量的线程完成执行,然后任何特定线程才能继续执行程序.每个线程在到达Barrier时都调用wait()函数.Barrier负责跟踪wait()调用的数量. ...

  8. js字符串怎么转python对象_python对象与json相互转换的方法 python中怎么把json对象转成字符串...

    在python中 如何实现将一个json字符串转化为对象 对象?json不能包含对象, 只能包含基本的数据类型, 键值对, 列表, 数字, 字符串等等 import jsond = {"k& ...

  9. cs精英游戏python代码_python面向对象-cs游戏示例

    #!/usr/local/bin/python3 # -*- coding:utf-8 -*- class Role(object): n = 123 # 类变量 name = "我是类na ...

最新文章

  1. 谷歌丰田联合成果ALBERT了解一下:新轻量版BERT,参数小18倍,性能依旧SOTA
  2. Rust即将发布1.0版本,Go持续获得关注:如何在新生语言之间做出抉择
  3. Dockerizing a Node.js web app
  4. WPF(C#)与MATLAB混合编程
  5. 设计模式学习笔记(9)——代理模式
  6. 简单几步,教你部署一个可扩展微服务系统!
  7. [转载] 《财富》评最受尊敬IT企业:苹果居首IBM次席
  8. Linux 文件系统与设备文件系统 (一)—— udev 设备文件系统
  9. CustomError可以设置绝对路径
  10. idea下载源码出现:Cannot download sources Sources not found for: org.apache.kafka:kafka-clients:2.3.0
  11. 当今主流软件产品家族及其开发语言
  12. 【ProcessOn】在线流程图、思维导图、原型图、UML图制作工具ProcessOn使用
  13. peoplesoft链接oracle,Oracle 调整对PeopleSoft HRMS8.8的支持延伸到2011年
  14. 快速简单的方法,彻底解决新浪微博自动关注营销号的问题
  15. 软件架构设计杂记: 好作品是改出来的,好的代码是不断重构打磨出来的, 心性是历经艰难困苦修炼出来的
  16. 调用短信、电话、邮件、Safari浏览器的系统API
  17. 【航线运输驾驶员理论考试】航空规章
  18. 深入浅出XDL(二):embedding
  19. 电商运营的要点有哪些
  20. 【AI简报20220311期】汽车AI芯片竞赛加速、苹果最强芯M1 Ultra登场

热门文章

  1. Java中break、Continue、reutrn总结
  2. Mac Vim 如何设置高亮
  3. 面向接口编程详解(一)——思想基础
  4. Android编程: MVC模式、应用的生命周期
  5. MessageBox不能应用皮肤的解决办法
  6. FlexUnit单元测试(第三章FlexUnit事件断言)
  7. MySQL--使用innodb_force_recovery修复数据库异常
  8. 解决父级元素高度塌陷问题的方法
  9. SQL Server 2008 R2占用内存越来越大解决方法
  10. Oracle安装错误“程序异常终止