图灵python大海之面向对象基础.pdf

  1. '''
  2. day1 -- day4 地基一定到打好
  3. 面向过程的编程思想
  4. 核心过程二字,过程指的是解决问题的步骤,即先干什么\再干什么\后干什么
  5. 基于该思想编写程序就好比在设计一条流水线,是一种机械式的思维方式
  6. 优点:复杂的问题流程化\进而简单化 (一步步去思考,写一步走一步)
  7. 缺点:可扩展性差
  8. (加一点参数或者方法可能改掉原来的代码,
  9. 一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,
  10. 即便是能,也得是大改,改一个组件,牵一发而动全身。)
  11. 就像打工自己需要技术,学历,工作经验等等
  12. 老板或者领导把事情安排好就ok了,员工只需要照着去做,能赚钱就OK
  13. 面向对象的编程思想
  14. 核心是对象二个字,对象是特征与技能的结合体
  15. 基于该思想编写程序(脑子始终想的是对象二字)就好比在创造一个世界,世界是由
  16. 一个个对象组成,在上帝眼里任何存在的事物都是对象,任何不存在的事物也都可以创造
  17. 出来,是一种上帝式的思维方式
  18. 优点: 可扩展性强 (比如:加属性加方法,有框架体系
  19. 对某一个对象单独修改,会立刻反映到整个体系中,
  20. 如对游戏中一个人物参数的特征和技能修改都很容易。)
  21. 缺点: 编程的复杂度要高与面向过程
  22. (难度高,要看应用场景
  23. 面向对象的程序设计看起来高大上,所以我在编程时就应该保证通篇类,
  24. 这样写出的程序一定是好的程序(面向对象只适合那些可扩展性要求比较高的场景)
  25. 比如,假设大海老师会降龙十八掌的十八掌,那么我每次跟人干仗都要从第一掌打到
  26. 第18掌降龙有悔
  27. 这才显得我很厉害:
  28. 面对敌人,我打到第三掌对方就已经倒下了,我说,不行,你给我起来,我还没有show完..
  29. 3.类有类属性,实例/对象有实例/对象属性,所以我们在定义class时一定要定义出那么几个类属性,
  30. 想不到怎么办,那就使劲的想,定义的越多越牛逼
  31. 这就犯了一个严重的错误,程序越早面向对象,死的越早,为啥面向对象,
  32. 因为我们要将数据与功能结合到一起,程序整体的结构都没有出来,
  33. 或者说需要考虑的问题你都没有搞清楚个八九不离十,你就开始面向对象了,
  34. 这就导致了,你在那里干想,自以为想通了,定义了一堆属性,结果后来又都用不到,
  35. 或者想不通到底应该定义啥,那就一直想吧,想着想着就疯了。
  36. 就像创业:
  37. 自己不太需要技术能力,只需要懂那些人拥有这些能力,因为我有钱
  38. 自己需要规划好创业的每一步,
  39. 招聘的时候人才的选择
  40. 技术
  41. 销售
  42. 门面的选择
  43. 类:
  44. 对象是特征与技能的结合体,而类则是一系列对象相同的特征与技能的结合体
  45. 强调:
  46. 1.对象是具体存在的事物,而类则一个抽象的概念
  47. 2.站在不同的角度总结出的类与对象是不同的
  48. 在现实世界中:先有一个个具体存在的对象,然后随着人类文明的发展才总结出类的概念
  49. '''
  1. # @Author : 大海
  2. # @File : 2.类的使用.py
  3. '''
  4. 老师
  5. 属性
  6. name='大海'
  7. age=18
  8. sex='男'
  9. 技能/方法/函数
  10. 上课
  11. class 定义类的关键字 类名首字母大写(约定俗成的)
  12. class 类名:
  13. pass
  14. 复杂的类名和变量一样
  15. # 驼峰体
  16. AgeOfDahai = 18
  17. 定义示例:
  18. class Person:
  19. pass
  20. '''
  21. #1. 先定义类
  22. class Teacher:
  23. # 相同的特征/属性/变量
  24. name = '大海'
  25. age = 18
  26. sex = '男'
  27. # 函数/方法/技能
  28. def course(self):
  29. # self到底是什么?
  30. # self当做一个位置形参
  31. print(self)
  32. print('course')
  33. return 222
  34. # print('类定义是运行的')
  35. #类是一系列对象相同的属性(变量)与技能(函数)的结合体,
  36. # 即类体中最常见的就是变量与函数的定义
  37. # 类体代码会在类定义阶段立即执行,会产生一个类的名称空间,
  38. print(Teacher.__dict__)
  39. name = 'oldname'
  40. print(name)
  41. # # 调用类的属性
  42. print(Teacher.name)
  43. print(Teacher.age)
  44. print(Teacher.sex)
  45. # 类的方法其实就是函数
  46. print(Teacher.course)
  47. # 函数加括号调用
  48. # ?????
  49. # self我们现在把它当作一个位置形参,但是为什么定义成self呢?
  50. Teacher.course(111)
  51. # 也有返回值
  52. oldname=Teacher.course(111)
  53. print(oldname)
  54. #不存在的属型或者方法会报错
  55. print(Teacher.xxx)
  56. # 修改类属性的值
  57. print(Teacher.name)
  58. #
  59. Teacher.name = '夏洛'
  60. #
  61. print(Teacher.name)
  62. # 添加类的属性
  63. Teacher.play = '篮球'
  64. print(Teacher.play)
  65. print(Teacher.__dict__)
  66. #
  67. # # 删除类的属性
  68. del Teacher.play
  69. #
  70. print(Teacher.play)
  71. print(Teacher.__dict__)
  72. # 总结:
  73. # 1. 类本质是一个用来存放变量与函数的容器
  74. # 2. 类的用途之一就是当做容器从其内部取出名字(变量与函数名)来使用
  75. # 3. 类的用途之二是调用类来产生对象 接下来讲对象
  1. # @Author : 大海
  2. # @File : 3.对象的使用.py
  3. #1. 先定义类
  4. class Teacher:
  5. # 相同的特征/属性/变量
  6. name = '大海'
  7. age = 18
  8. sex= '男'
  9. # 函数/方法/技能
  10. def course(self):
  11. # self到底是什么?
  12. # self当做一个位置形参
  13. print(self)
  14. print('course')
  15. return 222
  16. #2. 后调用类来产生对象:
  17. # 调用类的过程称之为类的实例的初始化,调用类的返回值称之为类的一个对象/实例
  18. # 调用类发生了?
  19. # 类是抽象 对象/实例是具象
  20. # 产生3个老师对象
  21. t1=Teacher()
  22. t2=Teacher()
  23. t3=Teacher()
  24. print(t1)
  25. print(id(t1))
  26. print(id(t2))
  27. print(id(t3))
  28. 对象独有的属性(没有独有的,从类里面去要)
  29. print(t1.__dict__)
  30. print(t1.name)
  31. print(t2.name)
  32. print(t3.name)
  33. 对象的方法(没有独有的,从类里面去要)
  34. print(t1.course)
  35. print(t2.course)
  36. print(t3.course)
  37. print(Teacher.__dict__)
  38. print('============')
  39. print(t1.__dict__)
  40. print(t2.__dict__)
  41. print(t3.__dict__)
  42. # 类有return
  43. oldname=Teacher.course(111)
  44. print(oldname)
  45. print('--------------')
  46. # 对象的方法
  47. # ?????
  48. #对象的方法执行,没有传入参数,self到底是什么?
  49. # 对比类方法执行,需要传入参数
  50. print(t1)
  51. a1=t1.course()
  52. print(a1)
  53. # 对象属性的修改
  54. # (类里面的属性)
  55. print(t1.name)
  56. print(t1.__dict__)
  57. # 添加了对象独有的属性
  58. t1.name = '夏洛'
  59. print(t1.name)
  60. print(t1.__dict__)
  61. # 删除对象的属性
  62. # 删除的是 t1.name = '夏洛'
  63. del t1.name
  64. print(t1.name)
  65. # # 对象完全独立 一个对象的操作不会对另一个对象影响
  66. print(t2.name)
  1. # @Author : 大海
  2. # @File : 4.生成对象__init__方法.py
  3. '''
  4. ### 1、初始化 *****
  5. 以双下划线开头且以双下划线结尾的固定方法,他们会在特定的时机被触发执行,
  6. __init__就是其中之一,它会在实例化之后自动被调用,以完成实例的初始化。
  7. '''
  8. #1. 先定义类
  9. class Teacher:
  10. # 相同的特征/属性/变量
  11. school = 'tuling'
  12. # 这个不对,不应该定义成类属性
  13. # name = '大海'
  14. # age = 18
  15. # sex= '男'
  16. def __init__(self,name,age,sex):
  17. self.name = name
  18. self.age = age
  19. self.sex = sex
  20. # 函数/方法/技能
  21. def course(self,name):
  22. # self到底是什么?
  23. # self当做一个位置形参
  24. print(self)
  25. print('course')
  26. print(name)
  27. print('-------------------')
  28. print('我是大海的属性%s'%self.name)
  29. print('我是大海的属性%s'%self.age)
  30. return '11111'
  31. # 产生3个老师对象
  32. # __init__没有就没有独有的对象属性
  33. t1=Teacher()
  34. print(t1.__dict__)
  35. t1.name = '夏洛'
  36. print(t1.name)
  37. print(t1.__dict__)
  38. # 有__init__方法,有了对象独有的属性
  39. dahai=Teacher('大海',18,'男')
  40. xialuo=Teacher('夏洛',22,'男')
  41. xishi=Teacher('西施',18,'女')
  42. # 对象的独立属性
  43. print(dahai.__dict__)
  44. # 类的属性 对象调用和类调用一样
  45. print(dahai.school)
  46. print(id(dahai.school))
  47. print(Teacher.school)
  48. print(id(Teacher.school))
  49. print(dahai)
  50. # # 对象独立的属性
  51. print(dahai.__dict__)
  52. # # 对象独立的属性
  53. print(xialuo.__dict__)
  54. # # __init__方法传入的属性类是没有的
  55. print(Teacher.__dict__)
  56. # 只是初始化的时候传入了参数,对象还是可以改属性值
  57. print(dahai.name)
  58. dahai.name = '顾安'
  59. print(dahai.__dict__)
  60. a1=dahai.course('wwwww')
  61. print(a1)
  1. # @Author : 大海
  2. # @File : 5.类的属性和对象属性的关系.py
  3. #1. 先定义类
  4. class Teacher:
  5. # 相同的特征/属性/变量
  6. school = 'tuling'
  7. xxx = '我是类的属性,也可能是对象的属性'
  8. yyy = 111
  9. def __init__(self,name,age,sex):
  10. self.name = name
  11. self.age = age
  12. self.sex = sex
  13. # 函数/方法/技能
  14. def course(self):
  15. # self到底是什么?
  16. # self当做一个位置形参
  17. print(self)
  18. # print('course')
  19. #
  20. # print('-------------------')
  21. # print('我是大海的属性%s'%self.name)
  22. # print('我是大海的属性%s'%self.age)
  23. # return '11111'
  24. # 实例初始化的时候必须传入参数,生成了对象的属性
  25. dahai = Teacher('大海', 18, '男')
  26. xialuo = Teacher('夏洛', 16, '男')
  27. xishi = Teacher('西施', 18, '女')
  28. # 对象属性的查找
  29. # 添加一个对象属性
  30. # dahai.xxx= '我是对象的属性'
  31. # 属性查找优先找对象,对象没有才去类里面找
  32. # print(dahai.xxx)
  33. # 类中定义的属性和方法是所有对象共享的,类可以用,对象也可以用
  34. # 类的属性给对象调用(原装)
  35. # print(id(dahai.yyy),dahai.yyy)
  36. # print(id(xialuo.yyy),xialuo.yyy)
  37. # print(id(xishi.yyy),xishi.yyy)
  38. # # # 类自己用
  39. # print(id(Teacher.yyy),Teacher.yyy)
  40. # 对象小气
  41. # print(Teacher.name)
  42. # 类的属性变化
  43. # 类改类的属性
  44. Teacher.yyy = 333
  45. # # 对象改类的属性(改不了)(实际上是自己添加了一个独有的属性)
  46. dahai.yyy = 2222
  47. # # # 类的属性给对象调用
  48. # # # 对象已经有了yyy属性的会优先考虑自己的
  49. print(id(dahai.yyy),dahai.yyy)
  50. print(id(xialuo.yyy),xialuo.yyy)
  51. print(id(xishi.yyy),xishi.yyy)
  52. # # 类自己用
  53. print(id(Teacher.yyy),Teacher.yyy)
  54. # ??????
  55. # 对象调用类的方法,不需要传入参数?
  56. print(id(dahai.course))
  57. print(dahai)
  58. dahai.course()
  59. print(id(xialuo.course))
  60. print(xialuo)
  61. xialuo.course()
  62. print(id(xishi.course))
  63. print(xishi)
  64. xishi.course()
  65. print('===============')
  66. # 类调用方法必须传入self参数对应的对象,因为方法里面需要使用这个self对象
  67. Teacher.course(dahai)
  68. Teacher.course(xialuo)
  69. Teacher.course(xishi)
  1. # @Author : 大海
  2. # @File : 6.绑定方法和非绑定方法.py
  3. # 类和对象的方法到底是怎样的
  4. # 我们一起来探究一下真相
  5. # self绑定给对象方法
  6. # 简单来说就是对象在调用方法的时候会自动把该对象传入
  7. # 该方法的参数一般这个参数我们用self表示
  8. # self绑定给对象方法
  9. class A:
  10. # # 作者@selfmethed省略了
  11. # # 因为类里面的方法大部分情况下是给实例化后的对象用
  12. def f(self,n):
  13. print(self,n)
  14. print('我是self的方法')
  15. #
  16. a = A()
  17. a1 = A()
  18. print(a)
  19. print('=================')
  20. # 是哪个对象调用的self参数的方法,那么传入的self就是那个对象
  21. a.f(1)
  22. print(a1)
  23. print('-----------------')
  24. a1.f(1)
  25. # # 类调用必须传入对象 不会自动传入对象 自己手动传入对象
  26. # print('*****************')
  27. A.f(a,1)
  28. A.f(a1,2)
  29. # 绑定类的方法是给类用的
  30. class B:
  31. # @classmethod
  32. def f(cls,n):# cls是一个规范,代表是绑定类的方法
  33. print(cls,n)
  34. print('我是绑定类的方法')
  35. print(B)
  36. print('============')
  37. B.f(1)
  38. # # 一般不这样用,绑定给类的方法给对象用
  39. b = B()
  40. print(b)
  41. b.f(1)
  42. # 非绑定方法/静态方法
  43. class C:
  44. @staticmethod
  45. def f(n):
  46. print(n)
  47. print('我是非绑定方法/静态方法')
  48. # # # 纯粹的函数,不会自动传入类
  49. C.f(2)
  50. c = C()
  51. # # # 纯粹的函数,不会自动传入对象
  52. c.f(3)
  53. # 总结
  54. '''
  55. 1、绑定方法(精髓在于自动传值)
  56. 特性:绑定给谁就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入
  57. 绑定方法分为两类:
  58. 1.1 绑定给对象方法
  59. 在类内部定义的函数(没有被任何装饰器修饰的),默认就是绑定给对象用的
  60. 1.2 绑定给类的方法:
  61. 在类内部定义的函数如果被装饰器 @classmethod 装饰,
  62. 那么则是绑定给类的,应该由类来调用,类来调用就自动将类当作第一个参数自动传入
  63. 2、非绑定方法(不会自动传值,就是一个 普通函数)
  64. 类中定义的函数如果被装饰器 @staticmethod 装饰,那么该函数就变成非绑定方法
  65. 优点
  66. 既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用
  67. 缺点
  68. 但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数
  69. 3 作用
  70. 如果函数体代码需要用外部传入的类,则应该将该函数定义成绑定给类的方法
  71. 如果函数体代码需要用外部传入的对象,则应该将该函数定义成绑定给对象的方法
  72. 如果函数体代码既不需要外部传入的类也不需要外部传入的对象,则应该将该函数定义成非绑定方法/普通函数
  73. '''
# @Author : 大海
# @File : 7.一切皆对象.py
# 在python中统一了类与类型的概念
class Foo:
    def find(self):
        print('我是绑定对象的方法')
# # <class '__main__.Foo'>
print(Foo)
obj = Foo()
# # <__main__.Foo object at 0x000001F7B83BEBC8>
print(obj)
obj.find()
# # obj的类型是Foo ,obj的类也是Foo
print(type(obj))



# # ctrl 按住不动 点击鼠标左键  可以查看源码
# print(str)
# # 其实python在'dahai'的前面自动加了一个str类
# name = str('dahai')
# # print(name)
# # # 面向对象的理解:str这个类实例化生成了name这个对象
# # # dahai这个值赋值给name这个变量
# # print(type(name))
# # # 面向对象的理解:name对象的方法
# # # 数据类型的方法
# print(name.startswith('d'))
#
# obj.find()

1.面向过程的编程思想

    以过程为核心,其主要思考的是解决问题的步骤,其编写程序就好比在设计一条流水线,是一种机械式的思维方式,

优点:复杂的问题流程化,进而简单化(一步步思考,写一步走一步)

缺点:可扩展性差

    (加一点参数或者方法可能改掉原来的代码,而不能使用,就像一条流水线只能生产一种东西)

.2面向对象的编程思想

    以对象为核心的编程思想,(对象是特征与技能的结合体)

    基于对象思想来编写的程序,就像是 在创造世界的一个个组成部分,(世界就是由一个个对象组成的,任何不存在的事物在上帝眼中也是可以被任意创造),这种基于对象来编写的程序,就是一种上帝创造万物的思维方式。

优点:可扩展性强 ·(比如:加属性,加方法,有框架体系,对某一个对象单独修改,会立刻反映到整个体系中。

缺点:编程难度高

3.类有类属性

实例/对象有实例/对象属性,所以在定义class时,通常要定义几个类属性。

但编写程序需要将数据与功能结合,需要先将程序的整体结构框架构造出来,再进行针对 性地面向对象,构建对象属性。以避免做大量的无用功。

对象是特征与技能的结合体,而类则是一系列对象相同的特征与技能的结合体。

强调:

1.对象是具体存在的事物,而类则是一个抽象的概念

2.站在不同的角度总结出的类与对象是不同的

Class定义类的关键字, 类的首字母要大写

class 类名:

    pass

复杂的类名和变量一样

驼峰体 :AgeOfDahai=18

定义示例:

class Person:

    pass

定义的类函数中,都会有个位置形参,self(类中都需要先以自身为变量)

类的方法其实就是函数,可以按照函数运行,但应注意传入参数

1.变量及函数的容器

类定义时,其本身是运行的,

类是一系列具有相同属性(变量)与技能(函数)的对象的结合体

即类 体中最常见的就是变量与函数的定义

类体代码会在类定义阶段立即执行 ,会产生一个类的名称空间

在类中调用不存在的属性或方法,会报错

类属性中的值可以修改

class Teacher:    #相同的特征/属性/变量  
    name="大海"  
    age=18 
    sex='男' 
    def course(self): 
        print(self)  
        print('course')  
        print('类定义是运行的')

print(Teacher.__dict__)
print(Teacher.name)
print(Teacher.course)      #类的方法其实就是函数。
Teacher.name='范'        #修改类的属性
print(Teacher.name)        
# 添加类的属性
Teacher.play='篮球'
print(Teacher.play)
print(Teacher.__dict__)
# 删除类的属性
del Teacher.play
print(Teacher.__dict__)

总结:

1.类的本质是一个用来存放变量与函数 的容器

2.类的用途之一就是当做容器从其内部取出名字(变量与函数名)来使用

3.类的用途之二是调用类来产生对象,

2.调用类来产生对象

调用类的过程称之为类的实例的初始化,调用类的返回值称之为类的一个对象/实例

每次的调用类结果都会产生一个新的对象,生成的对象拥有类的属性和方法

t1=Teacher()
t2=Teacher()
t3=Teacher()

print(id(t1))    #输出:17144944
print(id(t2))    #输出:17144912
print(id(t3))    #输出:17144880

t1.name='夏洛'   #为对象添加属性
print(t1.name)
print(t1.__dict__)

del t1.name   #删除对象的属性
print(t1.__dict__)

#两个对象各自独立,对一个对象的操作不影响另一个对象

初始化

对象 的属性同样可以修改

对象的属性独立,对象调用与类调用一样,

class Teacher: 
    school='tuling'   
    def __init__(self,name,age,sex):      
        self.name=name      
        self.age=age      
        self.sex=sex

t1=Teacher('大海','18','男')
print(t1.name)

对象与类的关系

1.对象可以调用类的属性,而类无法调用对象独有的属性

2.对象定义了新的属性(变量赋予新值)后,就不再调用类的属性,此时再加修改也是修改的对象本身的属性2.

3.对象调用类的方法时,如果只有self参数,则不需要传入实参,self传入的是对象本身

    (调用类的函数的方法:调用时必须传入self参数对应的对象,因为函数方法里面需要使用这个self对象)

绑定方法与非绑定方法

绑定给对象方法

简单来说就 是对象在调用方法的时候会自动把该对象传入,该方法的参数一般 用self来表示,传入对象本身

class A:  
    def f(self,n):    
        print(self,n)   
        print('我 self方法')

a=A()
a1=A()
print(a)
print('=====')
#self 的值 即为调用类的对象本身
a1.f(1)
print(a1)
print('----')
a1.f(2)
#类调用必须传入对象,不会自动传入对象,因此 ,需要手动传入
A.f(a,1)
A.f(a1,2)

绑定给类的方法

是给类使用的(传入类本身),即使被对象调用,默认绑定传入的也是类本身

class B:    
    @classmethod  
    def f(cls,n):    
        print(cls,n)      
        print('绑定类的方法')

print(B)
print('------')
B.f(112)

非绑定方法/静态方法

纯粹的函数,不会自动传入对象或者类

class C:   
    @staticmethod 
    def f(n):        
        print(n)  
        print('非绑定方法/静态方法')     
C.f(2)        #输出:2
c=C()        #输出:非绑定方法/静态方法

总结

1、绑定方法(精髓在于自动传值)
特性:绑定给谁就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入

绑定方法分为两类:
1.1 绑定给对象方法
在类内部定义的函数(没有被任何装饰器修饰的),默认就是绑定给对象用的
1.2 绑定给类的方法:
在类内部定义的函数如果被装饰器 @classmethod 装饰,
那么则是绑定给类的,应该由类来调用,类来调用就自动将类当作第一个参数自动传入

2、非绑定方法(不会自动传值,就是一个 普通函数)
类中定义的函数如果被装饰器 @staticmethod 装饰,那么该函数就变成非绑定方法
优点
既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用
缺点
但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数

3 作用
如果函数体代码需要用外部传入的类,则应该将该函数定义成绑定给类的方法
如果函数体代码需要用外部传入的对象,则应该将该函数定义成绑定给对象的方法
如果函数体代码既不需要外部传入的类也不需要外部传入的对象,则应该将该函数定义成非绑定方法/普通函数

绑定方法可以自动传值

默认绑定给对象,自动传入对象本身; 绑定类,加个@classmethod,自动传入类本身

非绑定方法不会自动传值

@staticmethod 装饰,没有自动传值的效果,就像一普通函数,

但没有了与类或者对象的绑定,能够自由任意传值。

一切皆对象

在python 中统一了类与类型的概念,

即在python 中的内置函数 都是可按照类以及对象的方法来理解 。

所有的参数,值,函数,也都是一个个类的对象。

ctrl+鼠标左键 可查看源码解释

面向对象进行编程

1、易维护

采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的。

2、质量高

在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。

3、效率高

在软件开发时,根据设计的需要对现实世界的事物进行抽象,产生类。使用这样的方法解决问题,接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。

4、易扩展

由于继承、封装 、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。
————————————————
版权声明:本文为CSDN博主「一颗帅土豆啊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43819618/article/details/90146966