2019-01-11类

2019-01-11  本文已影响0人  遥远的她197

一,编程思想

1.面向过程编程 - 遇到问题直接将逻辑转换成代码
2.函数式编程 - 遇到问题就像找一个,写一个拥有相应功能的函数;以函数作为编程工具
3.面向对象编程 - 遇到问题就考虑可不可以有一个类来给我提供相应的功能和数据;以类和对象为编程工具

python既支持函数式编程也支持面向对象编程

# 面向过程
num1 = 34
num2 = 34
print(num1+num2)  # 万一求另两个那不是又重要写,麻烦

# 函数式编程


def sum1(num1, num2):
    return num1+num2


print(sum1(3, 34))   # 下次再求和直接输入数字就行了,不用重写代码,方便

二 认识类和对象(声明) 重点

1.什么是类, 什么是对象
类就是拥有相同功能和相同属性的对象的集合;类是抽象的
对象就是类的实例;对象是具体的

人是类, 唐浩就是人类的对象
车是类, 楼下停在...的那辆车就是对象
电脑是类, 我桌上这台黑色的电脑就是对象 (电脑很多颜色,型号成千上万所有是抽象的, 面前的电脑就是具体的体现)

2.类的声明
类中的内容包含功能(函数)和属性(变量/属性)
a.语法

class 类名:
      类的内容

b.说明
class - python声明类的关键字
类名 - 要求: 标识符, 不能是关键字
规范: 驼峰式命名(通过首字母大写来区分不同的单词);第一个字母要大写
" - 固定写法
类的内容 - 包含类的说明文档,属性和方法
属性就是声明在类中的变量
方法就是声明在类中的函数

userName
UserName -类名 (都是驼峰式命名)
user_name - pep8

3.对象的声明
语法:
类名() - 创建指定的类的对象并且返回

# 声明一个人类
class Person:
    """类的说明文档: 人类"""
    num = 61  # 类中的属性  也叫类的字段

    # 类中的方法
    def eat(self):   # eat就是类的变量
        print('人在吃饭')


# 创建Person类的对象;p1就是对象
p1 = Person()
print(p1)  # 类默认打印的都是地址

# 同一个类可以创建多个对象
p2 = Person()
print(p2)  # 此时地址不同,因为类是抽象的,有很多

p3 = p2
print(p3)  # 和p2的地址相同

三 对象方法

class 类名:
      类中的属性
      类中的方法

1.类中的方法
声明在类中的函数就是方法
类中的方法包括: 对象方法(实例方法), 类方法, 静态方法

2.对象方法:
a. 什么是对象方法
直接声明在类中的函数就是对象方法
有默认参数self
调用
通过'对象.方法()'的方式来调用(对象方法要通过对象来调用) 里面的方法就是函数变量名

b.参数self
当我们通过对象调用对象方法的时候,self不需要传参, 因为系统会自动将当前对象传递给self。
当前对象: 调用当前方法的对象(谁调用对象方法self就是谁)
注意: 当前类的对象能做的事情self都可以做 谁调用self就是谁

class Person:
    def run(self):
        # self = p1
        print('=====2swswsw====')
        print('self', self)  # self <__main__.Person object at 0x02113830> *3
        print('人在跑步')

    def eat(self, food):
        print('self2', self)  # <__main__.Person object at 0x00613830> *7
        print(food)

# run()  # name 'run' is not defined会报错,因为在类里面不能再外面调用
def main():
    print('=======')  # 打印顺序*1
    # 创建对象
    p1 = Person()
    # 通过对象p1调用对象方法
    print('p1', p1)  # 就是和self一样 p1 <__main__.Person object at 0x02113830> *2

    p1.run()  # 人在跑步 不用传参,传参之后(默认有个self)会有两个参数会报错  p1就是当前对象 *4
    # 调用对象方法只需要给出了self以外的其他参数传参
    print('======-----=======')  # *5
    p1.eat('包子')
    print(p1)  # *6


if __name__ == '__main__':
    main()

四 init方法和构造方法

1.init方法: __init__
init方法是类中的一个特殊的对象方法, 专门用来对创建的对象进行初始化。
当通过类创建对象的时候,系统就会自动调用__init__方法

2.构造方法
a.什么是构造方法
函数名和类名一样的函数就是构造方法, 专门用来创建对象。
python中声明类的时候系统会自动创建这个类对应的构造方法

b.构造方法的执行过程
当我们构造方法的时候内部会先在内存中开辟空间保存对象;然后用创建的这个对象去调用--init--方法,用来对对象进行初始化;
--init--方法调用结束后,返回对象.
内部操作:

def Person(*args, **kwargs):
    对象 = 创建对象
    对象.__init__(*args, **kwargs)
    return 对象

注意: 如果类的init除了self以外还有其他参数,那么我们在创建对象的时候需要给构造方法来给init方法传参

class Person:
    # 类中两个__开头并且__结尾的方法叫魔法方法。不需要主动调用,系统会自动调用
    def __init__(self):
        print('init被调用了')


class Dog:
    def __init__(self, x, y):
        print(x, y)
        print('dog的init')

# ==============构造方法和init的关系(了解)==============
# 构造方法的伪代码
def my_init(a, b):
    print('a', a, b)  # a 12 32
    print('my_init')


def my_Dog(*args, **kwargs):
    my_init(*args, **kwargs)


my_Dog(a=12, b=32)

# =====================================
def main():
    # 人类
    print('======')
    p1 = Person()  # init被调用了  这就是构造方法
    print('======')

    p2 = Person()  # init被调用了

    # 狗类
    dog1 = Dog('金毛', '花狗')  # 金毛 花狗 /n  dog的init  self不需要传参


if __name__ == '__main__':
    main()

五 对象属性

重要!!!
1.什么是对象属性
类中的属性分为类的字段和对象属性
a.对象属性 - 属性的值会因为对象不同而不一样,这种属性就应该声明为对象属性
声明在init方法中 - 位置
以'self.属性名 = 值'的方式来声明(这儿的属性就是对象属性,值随便赋值) - 方式
通过'对象.属性名'的方式来使用 - 使用

b.类的字段 - 属性的值不会因为对象不同而不同,这种属性就声明成类的字段
直接声明在类的里面,函数外面的变量就是类的字段
以'字段名 = 值'
通过'类.字段'的方式来使用

class Person:
    # 类的字段
    num = 61


Person.num = 100
# 修改类的字段的值
print(Person.num)


class Person:
    # 在init方法中声明对象属性
    def __init__(self):
        self.name = '张三'  # 这就是对象属性
        self.age = 18       # 这就是对象属性


p1 = Person()
# 获取对象属性的值
print(p1.name, p1.age)  # 张三 18

p2 = Person()
# 修改对象属性的值
p2.name = '李四'
print(p2.name, p1.age)  # 李四 18

class Person:
    # 在init方法中声明对象属性
    def __init__(self, name1='', age1=0):
        self.name = name1  # 这就是对象属性  name就是属性
        self.age = age1       # 这就是对象属性  age就是属性


p1 = Person('小明', 18)
# 获取对象属性的值
print(p1.name, p1.age)  # 小明 18

p2 = Person('小心', 20)
# 修改对象属性的值
p2.name = '李四'
print(p2.name, p2.age)  # 李四 20

# 练习: 创建Dog类,有属性名字, 类型, 年龄  (都是对象属性)
# 要求创建Dog的对象的时候:不能给年龄赋值,可以给类型赋值也可以不用给类型赋值,必须给名字赋值
# 添加对象方法eat:打印XXX在吃什么
class Dog:
    def __init__(self, name1='', type=''):
        self.name = name1
        self.type = type
        self.age = 0

    def eat(self, food):
        # self = dog1, food = '骨头'
        # self = dog2, food = '屎'
        print('%s在吃%s' % (self.name, food))


dog1 = Dog('小迪', '金毛')
print(dog1.name, dog1.type, dog1.age)
dog1.eat('骨头')

dog2 = Dog('旺财', '中华田园犬')
dog2.eat('屎')
练习:声明一个矩形类,拥有属性长和宽,拥有方法求面积和求周长
class Rect:
      def __init__(self, length, width):
          self.length = length
          self.width = width

      def perimeter(self):
          perimeter =(self.width + self.length) * 2
          print('矩形的周长是%d' % perimeter)

      def area(self):
          mianji = self.length * self.width
          print('矩形的面积是%d' % mianji)


rect1 = Rect(8, 9)
rect1.perimeter()
rect1.area()

六 对象属性的增删改查

python中对象中对象的属性支持增删改查
1.查(获取对象属性)
对象.属性

__XX__这就叫魔法方法
# 属性的增删改查
class Person:
    def __init__(self, name='', age=0, sex='女'):
        self.name = name
        self.age = age
        self.sex = sex

class Dog:
    # __slots__魔法
    # 约束当前类的对象最多能拥有那个属性
    __slots__ = ('name', 'color', 'age')
    def __init__(self, name='', color='黑色'):
        self.name = name
        self.color = color


def main():
    dog1 = Dog('大黄', '黄色')
    dog1.age = 2   # 有了__slots__就会报错,要想正确在__slots__添加'age'
    dog1.name = 'ss'



    print('================元素的增删改查============')
    p1=Person('小花')
    p2=Person('小红')
    p3=Person('小强')
    # 查
    """
    对象.属性   - 获取指定对象指定属性值;当属性不存在的时候会报错
    getattr(对象, 属性名:str) - 获取指定对象指定属性值
                               当属性不存在的时候如果给默认值赋了值,程序不会报错,并集将默认值作为结果
    """
    print(p1.name)  # 小花

    # 属性不确定的时候可以用getattr
    # attr = input('属性:')
    # print(getattr(p1.attr))

    # print(p1.name1)  # 报错 'Person' object has no attribute 'name1 属性不存在
    print(getattr(p1, 'name'))  # 小花
    # print(getattr(p1, 'name1'))  # 也会报错 'Person' object has no attribute 'name1 属性不存在,但可以通过N后面加默认值补救
    print(getattr(p1, 'name1', '小心'))  # 小心

    # 增/改
    """
    对象.属性 = 值   - 当属性存在的是修改属性的值;属性不存在的时候添加属性
    setattr(对象, 属性名, 值) - 当属性存在的是修改属性的值;属性不存在的时候添加属性
    """
    print('===========增/改============')
    # 修改属性
    p1.name = 'xiaohua'
    print(p1.name)
    # 添加属性
    p1.height = 180
    print(p1.height)

    setattr(p1, 'age', 28)
    print(p1.age)
    setattr(p1, 'weight', 200)
    print(p1.weight)

    # 删
    """
    del 对象.属性
    delattr(对象, 属性名)
    """
    print('==========删============')
    del p1.sex
    # print(p1.sex)  # 'Person' object has no attribute 'sex' 因为删了就没了

    delattr(p1, 'age')
    # print(p1.age)  # 'Person' object has no attribute 'sex' 因为删了就没了

    # 注意:对象属性的操作,只针对操作的那一个对象,不会影响其他对象
    # 如上面p1的增删 不会影响p2


if __name__ == '__main__':
    main()

七 内置属性

内置属性指的是我们创建类的时候系统自动给我们添加的属性(其实是通过继承获取到的)

class Person:
    """说明文档:人类"""
    # 类的字段
    num = 61
    # __slots__ = ('name', 'age', 'sex')  # 一打开对象的__dict__就不能使用,会报错
    # 对象属性
    def __init__(self, name='', age=0, sex='男'):
        self.name = name
        self.age = age
        self.sex = sex
    def eat(self, food):
        print('%s在吃%s' % (self.name, food))

    # 定制对象的打印格式(当我们通过print打印一个对象的时候,实质就是打印对象调用__repr__函数的返回值)
    # 这个函数的返回值必须是字符串
    def __repr__(self):
        # return '<%s.%s object at %s>' % (self.__class__.__module__, self.__class__.__name__, hex(id(self)))
        return '<' + str(self.__dict__)[1:-1] + 'at' + hex(id(self)) + '>'


def main():
    p1 = Person('小明', 18)
    print(p1)  # print(p1.__repr__())   # <'name': '小明', 'age': 18, 'sex': '男'at0x2ec330>
    # 1.类.__name__  获取的名字(字符串)
    print(Person.__name__, type(Person.__name__))  # Person <class 'str'>
    # 此时Person.__name__是字符串而不是类
    class_name = Person.__name__
    print(Person, class_name)  # <class '__main__.Person'> Person
    print(Person.__name__.upper())  # PERSON

    print('==========')
    # 2.对象.__class__ - 获取对象对应的类(结果是类)
    # 获取对象p1的类
    my_class = p1.__class__
    print(my_class)  # <class '__main__.Person'>
    # 可以将my_class当成类来使用
    p2 = my_class('小花')
    print(my_class.num)  # 61

    # 3.类.__doc__  -获取类的说明文档(字符串)
    print(Person.__doc__)  # 说明文档:人类

    # 获取对象p1对应的类的说明文档
    print(p1.__class__.__doc__)  # 说明文档:人类

    # 4.对象.__dict__ - 将对象转换成字典,将属性和值作为字典的键值对,
    # 可以查看对象的不同
    # 注意: 当给__slots__属性赋值后, 对象的__dict__属性就不能使用
    print(p1.__dict__)  # {'name': '小明', 'age': 18, 'sex': '男'}

    # 5.类.__module__ - 获取当前所在的模块的模块名
    print(Person.__module__)  # __main__如果没有if那句就是07内置属性

    # 6.类.__bases__  - 获取当前类的父类(元祖)
    print(Person.__bases__)  # (<class 'object'>,) object就是它的父类, 相当于有几个父亲


if __name__ == '__main__':
    main()

八 对象方法,类方法和静态方法的区别

1.对象方法:
a.怎么声明: 直接声明在类中
b.特点: 自带self参数,调用的时候不用传参,谁调用指向谁
c.怎么调用: 对象.方法()

2.类方法
a.怎么声明:声明函数前加@classmethod
b.特点: 自带默认参数cls; 调用的时候不用传参,系统会自动将调用函数的类传给它
(cls是谁调用就指向谁,类方法只能通过类来调用,所以cls就是当前类)
类能做的事情, cls都能做
c.怎么调用:通过类来调用, 类.方法()
方法就就是类中函数的变量名

3.静态方法
a.怎么声明: 声明函数前加@staticmethod
b.特点: 没有默认参数
c.怎么调用: 通过类来调用,类.方法()

4.类中怎么选择使用哪种方法:
如果实现类中的函数的功能需要使用对象的属性,那么这个函数就要声明 对象方法

实现函数的功能不需要使用对象的属性的前提下,如果需要类的字段, 就声明成 类方法

实现函数的功能既不需要对象属性也不需要类的字段就声明成 静态方法

class Person:
    num = 61
    @staticmethod
    def func3():
        print(Person.num)
        print('我是静态方法')

    @classmethod
    def func2(cls):
        print(cls.num)
        print('我是类方法2')

    @classmethod
    def func1(cls):
        # 说明类能做的,cls都能做
        p1 = cls()  # 用cls来创建对象

        print(p1)
        cls.num = 100  # cls来使用类的字段
        cls.func2()  # cls调用类方法

        print('cls:', cls)
        print('这是一个类方法')


def main():
    Person.func1()  # 这是一个类方法 类.方法(函数变量名)
    Person.func3()   # 我是静态方法

if __name__ == '__main__':
    main()
class Game(object):

   # 游戏最高分,类属性
   top_score = 0

   @staticmethod
   def show_help():
       print("帮助信息:让僵尸走进房间")
       
   @classmethod
   def show_top_score(cls):
       print("游戏最高分是 %d" % cls.top_score)

   def __init__(self, player_name):
       self.player_name = player_name

   def start_game(self):
       print("[%s] 开始游戏..." % self.player_name)
       
       # 使用类名.修改历史最高分
       Game.top_score = 999

# 1. 查看游戏帮助
Game.show_help()

# 2. 查看游戏最高分
Game.show_top_score()

# 3. 创建游戏对象,开始游戏
game = Game("小明")

game.start_game()

# 4. 游戏结束,查看游戏最高分
Game.show_top_score()
上一篇下一篇

猜你喜欢

热点阅读