-day18面向对象进阶

2023-11-04

day18 面向对象进阶

课程目标:掌握面向对象进阶相关知识点,能更加自如的使用面向对象来进行编程。

今日概要:

  • 成员

    • 变量
      • 实例变量
      • 类变量
    • 方法
      • 绑定方法
      • 类方法
      • 静态方法
    • 属性
  • 成员修饰符(公有/私有)

  • “对象嵌套”

  • 特殊成员

对比

问题:洗衣机里面有脏衣服,怎么洗干净?

面向过程的解决方法:

  1. 执行加洗衣粉的方法
  2. 执行加水的方法
  3. 执行洗衣服的方法
  4. 执行清洗的方法
  5. 执行烘干的方法

以上就是将解决这个问题的过程拆分成一个个方法(是没有对象去调用的),通过一个个方法的执行来解决问题、

面向对象的解决方法:

  1. 先弄出两个对象:“洗衣机” 对象 和 “人” 对象

  2. 针对对象 “洗衣机” 加入一些属性和方法: “洗衣服方法” “清洗方法” “烘干方法”

  3. 针对对象 “人” 加入熟悉和方法:" 加洗衣粉方法" “加水方法”

  4. 然后执行

    • 人.加洗衣粉
    • 人.加水
    • 洗衣机.洗衣服
    • 洗衣机.清洗
    • 洗衣机.烘干

    解决同一个问题,面向对象编程就是先抽象出对象,然后用对象执行方法的方式解决问题。面向对象是已功能来划分问题,而不是步骤。

1.成员

面向对象中的所有成员如下:

  • 变量
    • 实例变量
    • 类变量
  • 方法
    • 绑定方法
    • 类方法
    • 静态方法
  • 属性

通过面向对象进行编程时,会遇到很多种情况,也会使用不同的成员来实现,接下来我们来逐一介绍成员特性和应用场景。

在这里插入图片描述

1.1 变量

  • 实例变量,属于对象,每个对象中各自维护自己的数据。
  • 类变量,属于类,可以被所有对象共享,一般用于给对象提供公共数据(类似于全局变量)。

大原则:谁里边的东西谁去调用。

# 定义一个类
class Person(object):
    country = "中国"

    # 方法
    def __init__(self, name, age):
        self.name = name
        self.age = age
	# 方法
    def show(self):
        # message = "{}-{}-{}".format(Person.country, self.name, self.age)
        message = "{}-{}-{}".format(self.country, self.name, self.age)
        print(message)

print(Person.country) # 中国

# 通过类创建了一个对象,分别是name = "光头强", age = 20
p1 = Person("光头强",20)
# 访问自己对象中的值
print(p1.name)
print(p1.age)

# 在实例变量中没找到country会自动去关联的类变量中找
print(p1.country) # 中国

# 调用对象中的方法,通过p1.show(), 相当于self = p1
p1.show() # 中国-光头强-20

提示:当把每个对象中都存在的相同的示例变量时,可以选择把它放在类变量中,这样就可以避免对象中维护多个相同数据。

易错点 & 面试题

第一题:注意读和写的区别。

  • 读,优先来自己这读,没有则去关联的类变量中找。

  • 写,确认往谁里边写,就是改谁里边的值,不会跨关系去改变。

在这里插入图片描述

示例1:

class Person(object):
    country = "中国"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        message = "{}-{}-{}".format(self.country, self.name, self.age)
        print(message)

print(Person.country) # 中国

p1 = Person("光头强",20)
print(p1.name) # 光头强
print(p1.age) # 20
print(p1.country) # 中国
p1.show() # 中国-光头强-20

p1.name = "root"     # 在对象p1中讲name重置为root
p1.num = 19          # 在对象p1中新增实例变量 num=19
p1.country = "china" # 在对象p1中新增实例变量 country="china"

print(p1.country)   # china
print(Person.country) # 中国

示例2:

class Person(object):
    country = "中国"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        message = "{}-{}-{}".format(self.country, self.name, self.age)
        print(message)

print(Person.country) # 中国

Person.country = "美国"


p1 = Person("光头强",20)
print(p1.name) # 光头强
print(p1.age) # 20
print(p1.country) # 美国

第二题:继承关系中的读写

请添加图片描述

示例1:

读,如果通过p1去读取某个值,对象中有则去实例变量中找,没有则去关联的类中找,如果还没有会照着继承关系去找,且他们的内地地址都是一样的,指向Base类中的 country = “中国”。

class Base(object):
    country = "中国"


class Person(Base):

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        message = "{}-{}-{}".format(Person.country, self.name, self.age)
        # message = "{}-{}-{}".format(self.country, self.name, self.age)
        print(message)


# 读
print(Base.country) # 中国
print(Person.country) # 中国

obj = Person("光头强",19)
print(obj.country) # 中国

# 写,各自维护各自的一个country,所以取值是优先在自己这里去取
Base.country = "china"
Person.country = "泰国"
obj.country = "日本"

面试题

class Parent(object):
    x = 1


class Child1(Parent):
    pass


class Child2(Parent):
    pass


print(Parent.x, Child1.x, Child2.x) # 1 1 1

Child1.x = 2
print(Parent.x, Child1.x, Child2.x) # 1 2 1

Parent.x = 3
print(Parent.x, Child1.x, Child2.x) # 3 2 3

1.2 方法

  • 绑定方法,默认有一个self参数,由对象进行调用(此时self就等于调用方法的这个对象)【对象&类均可调用】
  • 类方法,默认有一个cls参数,用类或对象都可以调用(此时cls就等于调用方法的这个类)【对象&类均可调用】
  • 静态方法,无默认参数,用类和对象都可以调用。【对象&类均可调用】

请添加图片描述

# 定义类
class Foo(object):

    def __init__(self, name,age):
        self.name = name
        self.age = age

    def f1(self):
        print("绑定方法", self.name)

    @classmethod
    def f2(cls):
        print("类方法", cls)

    @staticmethod
    def f3():
        print("静态方法")
        
###  绑定方法(主流:对象):
# 实例化一个对象
obj = Foo("光头强",20)
# 通过对象执行一个f1()方法
obj.f1() #通过类调用 Foo.f1(obj),参数需要手动


# 类方法
Foo.f2()  # cls就是当前调用这个方法的类。(主流:类)
obj.f2()  # cls就是当前调用这个方法的对象的类。


# 静态方法
Foo.f3()  # 类执行执行方法(主流:类)
obj.f3()  # 对象执行执行方法

在Python中比较灵活,方法都可以通过对象和类进行调用;而在java、c#等语言中,绑定方法只能由对象调用;类方法或静态方法只能由类调用。

import os
import requests


class Download(object):

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

    @staticmethod
    def download_dou_yin():
        # 下载抖音
        res = requests.get('.....')

        with open("xxx.mp4", mode='wb') as f:
            f.write(res.content)

    def download_dou_yin_2(self):
        # 下载抖音
        res = requests.get('.....')
        path = os.path.join(self.folder_path, 'xxx.mp4')
        with open(path, mode='wb') as f:
            f.write(res.content)


obj = Download("video")
obj.download_dou_yin()

面试题:

在类中 @classmethod 和 @staticmethod 的作用?

@classmethod
装饰上这个方法变成了类方法,默认有一个cls参数,使用场景取决于方法内部实现的功能,如果用到了当前cls这个类,那么就选择@classmethod

@staticmethmod
装饰上这个方法变成了静态方法,默认没有参数,如果哪个参数都没有用上,只有简单的处理逻辑,选择静态方法更加合适。

1.3 属性

属性其实是由绑定方法 + 特殊装饰器 组合创造出来的,让我们以后在调用方法时可以不加括号

例如:

class Foo(object):

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

    def f1(self):
        return 123

    @property
    def f2(self):
        return 123


obj = Foo("光头强")

v1 = obj.f1()
print(v1)

#  通过调用 @property,不需要加括号,默认自己增加
v2 = obj.f2
print(v2)

示例:以之前开发的分页的功能。


class Pagination:
    def __init__(self, current_page, per_page_num=10):
        self.per_page_num = per_page_num
        
        if not current_page.isdecimal():
            self.current_page = 1
            return
        current_page = int(current_page)
        if current_page < 1:
            self.current_page = 1
            return
        self.current_page = current_page
	
    def start(self):
        return (self.current_page - 1) * self.per_page_num
	
    def end(self):
        return self.current_page * self.per_page_num


user_list = ["用户-{}".format(i) for i in range(1, 3000)]

# 分页显示,每页显示10条
while True:
    page = input("请输入页码:")
	
    # page,当前访问的页码
    # 10,每页显示10条数据
	# 内部执行Pagination类的init方法。
    pg_object = Pagination(page, 20)
    
    page_data_list = user_list[ pg_object.start() : pg_object.end() ]
    for item in page_data_list:
        print(item)

优化后

class Pagination:
    def __init__(self, current_page, per_page_num=10):
        self.per_page_num = per_page_num

        if not current_page.isdecimal():
            self.current_page = 1
            return
        current_page = int(current_page)
        if current_page < 1:
            self.current_page = 1
            return
        self.current_page = current_page

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num


user_list = ["用户-{}".format(i) for i in range(1, 3000)]

# 分页显示,每页显示10条
while True:
    page = input("请输入页码:")

    pg_object = Pagination(page, 20)
    page_data_list = user_list[ pg_object.start : pg_object.end ]
    
    for item in page_data_list:
        print(item)

其实,除了咱们写的示例意外,在很多模块和框架的源码中也有porperty的身影,例如:requests模块。

import requests
from requests.models import Response
# 内部下载视频,并将下载好的数据分装到Response对象中。
res = requests.get(
    url="https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
    }
)

# 去对象中获取text,其实需要读取原始文本字节并转换为字符串
print(type(res)) # <class 'requests.models.Response'>



# ctrl 点击进入  Response

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3KSHF8Bf-1637761343938)(images/image-20211106163213233.png)]

关于属性的编写有两种方式:

  • 方式一,基于装饰器

    class C(object):
        
        @property
        def x(self):
            pass
        
        @x.setter
        def x(self, value):
            pass
        
        @x.deleter
        def x(self):
    		pass
            
    obj = C()
    
    obj.x
    obj.x = 123
    del obj.x
    
  • 方式二,基于定义变量

    class C(object):
        
        def getx(self): 
    		pass
        
        def setx(self, value): 
    		pass
            
        def delx(self): 
    		pass
            
        x = property(getx, setx, delx, "I'm the 'x' property.")
        
    obj = C()
    
    # 自动触发调用第一个参数,并且得到它的返回值
    obj.x
    
    # 自动触发调用第二个参数
    obj.x = 123
    
    # 自动触发调用第三个参数
    del obj.x
    
    
    # "I'm the 'x' property." 是注释,放在了第四个参数的位置
    
    # 如果不需要后边这两个参数,则可以写成None
    x = property(getx, None, None, "I'm the 'x' property.")
    

Django源码一撇:

class WSGIRequest(HttpRequest):
    def __init__(self, environ):
        script_name = get_script_name(environ)
        # If PATH_INFO is empty (e.g. accessing the SCRIPT_NAME URL without a
        # trailing slash), operate as if '/' was requested.
        path_info = get_path_info(environ) or '/'
        self.environ = environ
        self.path_info = path_info
        # be careful to only replace the first slash in the path because of
        # http://test/something and http://test//something being different as
        # stated in https://www.ietf.org/rfc/rfc2396.txt
        self.path = '%s/%s' % (script_name.rstrip('/'),
                               path_info.replace('/', '', 1))
        self.META = environ
        self.META['PATH_INFO'] = path_info
        self.META['SCRIPT_NAME'] = script_name
        self.method = environ['REQUEST_METHOD'].upper()
        # Set content_type, content_params, and encoding.
        self._set_content_type_params(environ)
        try:
            content_length = int(environ.get('CONTENT_LENGTH'))
        except (ValueError, TypeError):
            content_length = 0
        self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
        self._read_started = False
        self.resolver_match = None

    def _get_scheme(self):
        return self.environ.get('wsgi.url_scheme')

    def _get_post(self):
        if not hasattr(self, '_post'):
            self._load_post_and_files()
        return self._post

    def _set_post(self, post):
        self._post = post

    @property
    def FILES(self):
        if not hasattr(self, '_files'):
            self._load_post_and_files()
        return self._files

    POST = property(_get_post, _set_post)

写在最后,对属性进行一个补充:

由于属性和实例变量的调用方式相同,所以在编写时需要注意:属性名称 不要 与实例变量 重名。

class Foo(object):

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @property
    def func(self):
        return 123


obj = Foo("光头强", 123)
print(obj.name)
print(obj.func)

一旦重名,可能就会有报错。

class Foo(object):

    def __init__(self, name, age):
        self.name = name  # 报错,错认为你想要调用 @name.setter 装饰的方法。
        self.age = age

    @property
    def name(self):
        return "{}-{}".format(self.name, self.age)


obj = Foo("光头强", 123)
class Foo(object):

    def __init__(self, name, age):
        self.name = name 
        self.age = age

    @property
    def name(self):
        return "{}-{}".format(self.name, self.age) # 报错,循环调用自己(直到层级太深报错)

    @name.setter
    def name(self, value):
        print(value)


obj = Foo("光头强", 123)
print(obj.name)

如果真的想要在名称上创建一些关系,可以让实例变量加上一个下划线。

class Foo(object):

    def __init__(self, name, age):
        self._name = name
        self.age = age

    @property
    def name(self):
        return "{}-{}".format(self._name, self.age)


obj = Foo("光头强", 123)
print(obj._name)
print(obj.name)

2.成员修饰符

Python中成员的修饰符就是指的是:公有、私有。

  • 公有,在任何地方都可以调用这个成员。
  • 私有,只有在类的内部才可以调用该成员(成员是以两个下划线开头,则表示该成员为私有)。

示例一:

实例变量

class Foo(object):

    def __init__(self, name, age):
        self.__name = name
        self.age = age

    def get_data(self):
        return self.__name

    def get_age(self):
        return self.age


obj = Foo("光头强", 123)
# obj.__name # 无法访问

# 公有成员
print(obj.age)
v1 = self.get_age()
print(v1)

# 私有成员
# print(obj.__name) # 错误,由于是私有成员,只能在类中进行使用。
v2 = obj.get_data()
print(v2)


# 类变量也是同样的

示例2:

对方法而言

class Foo(object):

    def get_age(self):
        print("公有的get_age")

    def __get_data(self):
        print("私有的__get_data方法")

    def proxy(self):
        print("公有的proxy")
        self.__get_data()


obj = Foo()
obj.get_age()

obj.proxy()

# 静态方法,类方法也有公有私有之分,和这个调用方式,规则也是一样的

示例3:

属性也可以通过下划线指定公有和私有

class Foo(object):

    @property
    def __name(self):
        print("公有的get_age")

    @property
    def proxy(self):
        print("公有的proxy")
        self.__name
        return 1


obj = Foo()
v1 = obj.proxy
print(v1)

# 三类成员:类实例变量,方法,属性

特别提醒:父类中的私有成员,子类无法继承。

class Base(object):

    def __data(self):
        print("base.__data")

    def num(self):
        print("base.num")


class Foo(Base):

    def func(self):
        self.num()
        self.__data() # # 不允许执行父类中的私有方法


obj = Foo()
obj.func()

class Base(object):

    def __data(self):
        print("base.__data")

    def num(self):
        print("base.num")
        self.__data()  # 不允许执行父类中的私有方法


class Foo(Base):

    def func(self):
        self.num()


obj = Foo()
obj.func()

写在最后,按理说私有成员是无法被外部调用,但如果用一些特殊的语法也可以(Flask源码中有这种写法,大家写代码不推荐这样写)。

class Foo(object):

    def __init__(self):
        self.__num = 123
        self.age = 19

    def __msg(self):
        print(1234)


obj = Foo()
print(obj.age)
print(obj._Foo__num) # 一个下划线 + 当前类类名 __ + 私有方法名
obj._Foo__msg()

成员是否可以作为独立的功能暴露给外部,让外部调用并使用。

  • 可以,公有。
  • 不可以,只是作为内部其他方法的一个辅助,这时候选择变为私有的。

3.对象嵌套

在基于面向对象进行编程时,对象之间可以存在各种各样的关系,例如:组合、关联、依赖等(Java中的称呼),用大白话来说就是各种嵌套。

下面我们就用示例来学习常见的嵌套的情景:

情景一:

一个对象中嵌套另外一个对象

# 创建了学生类
class Student(object):
    """ 学生类 """

# 定义姓名,年龄
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 定义Student对象object
    def message(self):
        data = "我是一名学生,我叫:{},我今年{}岁".format(self.name, self.age)
        print(data)

s1 = Student("光头强", 19)
s2 = Student("Geek", 19)
s3 = Student("熊大", 19)


# 创建了班级类
class Classes(object):
    """ 班级类 """

    def __init__(self, title):
        self.title = title
        self.student_list = []

    def add_student(self, stu_object):
        self.student_list.append(stu_object)

    def add_students(self, stu_object_list):
        for stu in stu_object_list:
            self.add_student(stu)

    def show_members(self):
        for item in self.student_list:
            # print(item)
            item.message()

c1 = Classes("三年二班")
c1.add_student(s1)
c1.add_students([s2, s3])

print(c1.title)
print(c1.student_list)

情景二:

class Student(object):
    """ 学生类 """

    def __init__(self, name, age, class_object):
        self.name = name
        self.age = age
        self.class_object = class_object

    def message(self):
        data = "我是一名{}班的学生,我叫:{},我今年{}岁".format(self.class_object.title, self.name, self.age)
        print(data)


class Classes(object):
    """ 班级类 """

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

# 创建了两个班级对象
c1 = Classes("Python全栈")
c2 = Classes("Linux云计算")

user_object_list = [
    Student("光头强", 19, c1),
    Student("Geek", 19, c1),
    Student("熊大", 19, c2)
]

for obj in user_object_list:
    print(obj.name,obj.age, obj.class_object.title)

情景三:

class Student(object):
    """ 学生类 """

    def __init__(self, name, age, class_object):
        self.name = name
        self.age = age
        self.class_object = class_object

    def message(self):
        data = "我是一名{}班的学生,我叫:{},我今年{}岁".format(self.class_object.title, self.name, self.age)
        print(data)


class Classes(object):
    """ 班级类 """

    def __init__(self, title, school_object):
        self.title = title
        self.school_object = school_object


class School(object):
    """ 学校类 """

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


s1 = School("北京校区")
s2 = School("上海校区")

c1 = Classes("Python全栈", s1)
c2 = Classes("Linux云计算", s2)

user_object_list = [
    Student("光头强", 19, c1),
    Student("Geek", 19, c1),
    Student("熊大", 19, c2)
]
for obj in user_object_list:
    print(obj.name, obj.class_object.title ,  obj.class_object.school_object.name)

4.特殊成员

在Python的类中存在一些特殊的方法,这些方法都是 __方法__ 格式,这种方法在内部均有特殊的含义,接下来我们来讲一些常见的特殊成员:

  • __init__,初始化方法,在生产对象时调用

    class Foo(object):
        def __init__(self, name):
            self.name = name
    
    # 实例化对象时,会自动化执行,并将变量 "光头强" 传递给 参数 name
    obj = Foo("光头强")
    
  • __new__,构造方法

    class Foo(object):
        def __init__(self, name):
            print("第二步:初始化对象,在空对象中创建数据")
            self.name = name
            
        # 先执行 __new__方法,而不是 __init__方法
        def __new__(cls, *args, **kwargs):
            print("第一步:先创建空对象并返回")
            return object.__new__(cls)
    
    
    obj = Foo("光头强")
    # 在初始化 __init__ 之前执行,作用:调用object.__new__ 帮助我们创建一个空对象并返回
    # 执行类中的 init方法,init中的self就是new方法创建的空对象且返回的值
    # 写代码过程中会可以省略不写,在内部也会执行new方法,只不过没有Foo这个类就回去它的父类中去查找,在它的父类中的new会把对象创建
    
  • __call__ 对象 + 括号 自动执行类中的 __call__ 方法,函数调用

    class Foo(object):
        def __call__(self, *args, **kwargs):
            print("执行call方法")
    
    
    obj = Foo()
    obj()
    
  • __str__ 打印对象时,会调用对象 __str__ 方法,默认会打印类名和对象的地址名;

    class Foo(object):
    
        def __str__(self):
            return "哈哈哈哈"
    
    
    obj = Foo()
    data = str(obj)
    print(data)
    
    # 例:
    
    class Student(object):
        """学生类"""
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return "{}--{}".format(self.name, self.age)
    
    
    s1 = Student("马冬梅", 16)
    s2 = Student("夏洛", 17)
    
    data1 = str(s1)
    data2 = str(s2)
    print(data1)
    print(data2)
    
  • __dict__ 获取类和对象的信息【属性和方法】,转换成自动返回

    class Foo(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    obj = Foo("光头强",19)
    print(obj.__dict__)
    
  • __getitem__ 按照索引获取值, __setitem__安装索引赋值, __delitem__

    class Foo(object):
    
        def __getitem__(self, item):
            pass
    
        def __setitem__(self, key, value):
            pass
    
        def __delitem__(self, key):
            pass
    
    
    obj = Foo("光头强", 19)
    
    obj["x1"]
    obj['x2'] = 123
    del obj['x3']
    
    # TypeError: Foo() takes no arguments
    

    字典对象支持:

    • 对象[“xxx”]
    • 对象[“xxx”] = 123
    • del 对象[“xxx”]
    class Foo(object):
    
        def __setitem__(self, key, value):
            print(key, value)
    
        def __getitem__(self, item):
            print(item)
    
        def __delitem__(self, key):
            print(key)
    
    
    obj = Foo()
    
    obj['xxx'] = 123  # 自动触发类中的 __setitem__
    obj["yyy"]  # 自动触发类中的 __getitem__
    del obj['zzz']  # 自动触发类中的 __delitem__
    
  • __enter____exit__

    class Foo(object):
    
        def __enter__(self):
            print("进入了")
            return 666
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("出去了")
    
    
    obj = Foo()
    
    # with 对象  as  f  在内部会执行 __enter__方法
    # 当with缩进中的代码执行完毕,会自动执行__exit__
    
    with obj as data:
        print(data)
    
    超前知识:数据连接,每次对远程的数据进行操作时候都必须经历。
    1.连接 = 连接数据库
    2.操作数据库
    3.关闭连接
    
    class SqlHelper(object):
    
        def __enter__(self):
            self.连接 = 连接数据库
            return 连接
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.连接.关闭
    
            
            
    with SqlHelper() as 连接:
        连接.操作..
        
        
    with SqlHelper() as 连接:
        连接.操作...
    
    # 面试题(补充代码,实现如下功能)
    
    class Context:
        
        def do_something(self):
            print('内部执行')
    
    
    with Context() as ctx:
        print('内部执行')
        ctx.do_something()
    
    

    上下文管理的语法。

    • __add__ 加运算。__sub__减运算,__mul__ 乘运算,__truediv__除运算,__mod__求余运算,__pow__ 乘方
    class Foo(object):
        def __init__(self, name):
            self.name = name
    
        def __add__(self, other):
            return "{}-{}".format(self.name, other.name)
    
    
    v1 = Foo("Geek")
    v2 = Foo("Good")
    
    # 对象+值,内部会去执行 对象.__add__方法,并将+后面的值当做参数传递过去。
    v3 = v1 + v2
    print(v3)
    
  • __iter__

    • 迭代器

      # 迭代器类型的定义:
          1.当类中定义了 __iter__ 和 __next__ 两个方法。
          2.__iter__ 方法需要返回对象本身,即:self
          3. __next__ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration停止跌停的异常。
      	官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types
              
      # 创建 迭代器类型 :
      	class IT(object):
              def __init__(self):
                  self.counter = 0
      
              def __iter__(self):
                  return self
      
              def __next__(self):
                  self.counter += 1
                  if self.counter == 3:
                      raise StopIteration()
                  return self.counter
      
      # 根据类实例化创建一个迭代器对象:
          obj1 = IT()
          
          # v1 = obj1.__next__()
          # v2 = obj1.__next__()
          # v3 = obj1.__next__() # 抛出异常
          
          v1 = next(obj1) # obj1.__next__()
          print(v1)
      
          v2 = next(obj1)
          print(v2)
      
          v3 = next(obj1)
          print(v3)
      
      
          obj2 = IT()
          for item in obj2:  # 首先会执行迭代器对象的__iter__方法并获取返回值,一直去反复的执行 next(对象),并返回给 item
              print(item)
              
      迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration。
      for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。
      
    • 生成器

      # 创建生成器函数
          def func():
              yield 1
              yield 2
          
      # 创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__ 方法。
          obj1 = func()
          
          v1 = next(obj1)
          print(v1)
      
          v2 = next(obj1)
          print(v2)
      
          v3 = next(obj1)
          print(v3)
      
      
          obj2 = func()
          for item in obj2:
              print(item)
      
      如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类(生成器也是一个中特殊的迭代器)。
      
    • 可迭代对象

      # 如果一个类中有__iter__方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。
      
      class Foo(object):
          
          def __iter__(self):
              return 迭代器对象(生成器对象)
          
      obj = Foo() # obj是 可迭代对象。
      
      # 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
      for item in obj:
          pass
      
      class IT(object):
          def __init__(self):
              self.counter = 0
      
          def __iter__(self):
              return self
      
          def __next__(self):
              self.counter += 1
              if self.counter == 3:
                  raise StopIteration()
              return self.counter
      
      
      class Foo(object):
          def __iter__(self):
              return IT()
      
      
      obj = Foo() # 可迭代对象
      
      
      for item in obj: # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象;不断地执行迭代器对象的next方法。
          print(item)
      
      # 基于可迭代对象&迭代器实现:自定义range
      class IterRange(object):
          def __init__(self, num):
              self.num = num
              self.counter = -1
      
          def __iter__(self):
              return self
      
          def __next__(self):
              self.counter += 1
              if self.counter == self.num:
                  raise StopIteration()
              return self.counter
      
      
      class Xrange(object):
          def __init__(self, max_num):
              self.max_num = max_num
      
          def __iter__(self):
              return IterRange(self.max_num)
      
      
      obj = Xrange(100)
      
      for item in obj:
          print(item)
      
      class Foo(object):
          def __iter__(self):
              yield 1
              yield 2
      
      
      obj = Foo()
      for item in obj:
          print(item)
      
      # 基于可迭代对象&生成器 实现:自定义range
      
      class Xrange(object):
          def __init__(self, max_num):
              self.max_num = max_num
      
          def __iter__(self):
              counter = 0
              while counter < self.max_num:
                  yield counter
                  counter += 1
      
      
      obj = Xrange(100)
      for item in obj:
          print(item)
      

      常见的数据类型:

      v1 = list([11,22,33,44])
      
      v1是一个可迭代对象,因为在列表中声明了一个 __iter__ 方法并且返回一个迭代器对象。
      
      from collections.abc import Iterator, Iterable
      
      v1 = [11, 22, 33]
      print( isinstance(v1, Iterator) )  # false,判断是否是迭代器;判断依据是__iter__ 和 __next__。
      v2 = v1.__iter__()
      print( isinstance(v2, Iterator) )  # True
      
      
      
      v1 = [11, 22, 33]
      print( isinstance(v1, Iterable) )  # True,判断依据是是否有 __iter__且返回迭代器对象。
      
      v2 = v1.__iter__()
      print( isinstance(v2, Iterable) )  # True,判断依据是是否有 __iter__且返回迭代器对象。
      

      __len__ 获得长度

迭代器概念-理解(1)

迭代器

迭代器是python最强大的功能之一,是访问集合元素的一种方式。

迭代器是一个可以记住变量的位置的对象。

迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束,迭代器只能往前不能完后。

迭代器有两个基本的方法:iter() 和 next()。

字符串,列表或元组对象都可用于创建迭代器。

list = [1, 2, 3, 4]
it = iter(list)  # 创建迭代器对象
print(next(it))  # 输出迭代器的下一个元素:1
print(next(it))  # 2

迭代器对象可以使用常规for语句进行遍历

list = [1, 2, 3, 4]
it = iter(list)  # 创建迭代器对象
for x in it:
    print(x)

也可以使用next()函数

import sys
list = [1, 2, 3, 4]
it = iter(list)  # 创建迭代器对象

while True:
    try:
        print(next(it))
    except StopIteration:
        sys.exit()

创建一个迭代器

把一个类作为一个迭代器使用需要在类中实现两个方法__iter__()__next__()

在面向对象中,类都有一个构造函数,python的构造函数为 __init__() 方法并通过StopIteration 异常表示迭代的完成。

__next__() 方法python2中是next() 会返回下一个迭代器对象

创建一个返回数字的迭代器,初始值为 1,逐步递增 1:

class Mynumber():
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        x = self.a
        self.a += 1
        return x

Myclass = Mynumber()
myiter = iter(Myclass)

print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

StopIteration

StopIteration异常用于表示和迭代的完成,放在出现无线循环的情况,在 __next__() 方法中可以设置在完成指定循环次数后触发 StopIteration异常来结束迭代。

class mynumbers():
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        if self.a <= 20:
            x = self.a
            self.a += 1
            return x
        else:
            raise StopIteration


myclass = mynumbers()
myiter = iter(myclass)

for x in myiter:
    print(x)

生成器

在python中,使用了yield的函数被称为生成器(generator)。

根普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解成生成器就是一个迭代器。

在调用生成器运行的过程中,每次遇到yield时,函数会暂停并保存当前所运行的信息,返回yield的值,并在下一次执行next()方法时从当前位置继续运行。

调用一个生成器函数,返回的是一个迭代器对象。

实例:使用yield 实现 斐波那契数列

import sys

def fibonacci(n):   # 生成器函数, 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n):
            return
        yield a
        a, b = b, a + b
        counter += 1


f = fibonacci(10)  # f 是一个的确,由生成器返回生成

while True:
    try:
        print(next(f), end =' ')
    except StopIteration:
        sys.exit()

迭代器(2)

1.什么是迭代器

迭代器指的是迭代取值的工具,迭代是一个重复的过程,每一次重复都是基于上一次的结果而继续的,单纯的重复部署迭代。

count = 0
while count < 5:
    print(count)
    count += 1

2.为何要有迭代器?

迭代器是用来迭代取值的工具,而涉及到把多个值循环取出来的类型有:列表,字符串,元组,字典,集合,文件。

l = [1, 2, 3, 4]
i = 0
while i < len(l):
    print(l[i])
    i += 1

上述迭代取值的方式只适用于有索引的数据类型:列表,字符串,元组。为了解决基于索引迭代器取值的局限性,python必须提供一种能够不依赖于索引的取值方式,这就是迭代器。

3.如何使用迭代器?

可迭代对象:但凡内置有 __iter__方法的都称之为可迭代的对象。可以理解为可转换为迭代器的对象。

如下都是可迭代的对象。
s1 = ''
s1.__iter__()

l = []
l.__iter__()

d = {'a': 1}
d.items()

set1 = {1, 2, 3}
set1.__iter__()

with open('a.txt', mode='w') as f:
    f.__iter__()
    # 打开的文件对象是可迭代的对象,有
    f.__next__()


# 调用可迭代对象下的 __iter__方法将其转换成迭代器对象
d = {'a': 1, 'b': 2, 'c': 3}
res = d.__iter__()
print(res)   # <dict_keyiterator object at 0x0000023B99AB2450>
d = {'a': 1, 'b': 2, 'c': 3}
res = d.__iter__()

print(res.__next__()) # a
print(res.__next__()) # b
print(res.__next__()) # c
print(res.__next__()) # StopIteration 抛出异常
d = {'a': 1, 'b': 2, 'c': 3}
res = d.__iter__()

while True:
    try:
        print(res.__next__())
    except StopIteration:
        break

print('=====>>>>') # 在一个迭代器取值取干净的情况下,再对其取值,取不到
# 再次调用就能取到
res = d.__iter__()
while True:
    try:
        print(res.__next__())
    except StopIteration:
        break

总结:有了迭代器掌握了一种统一的迭代取值方式,并不限于基于索引的取值方式,它适用于:列表,字符串,元组,字典,集合,文件,全都适用。

迭代器与for循环工作原理

可迭代器对象与迭代器对象详解

可迭代对象有:字符串,列表,元组。字典,集合,文件对象

迭代器对象有:文件对象

可迭代对象(可以转换成的迭代器的对象):内置有 __iter__ 方法对象

  • 可迭代对象.__iter__() : 得到迭代器对象

迭代器对象:内置有 __next__并且内置有 __iter__ 方法的对象。

  • 迭代器对象.__next__() : 得到迭代器的下一个值

  • 迭代器对象.__iter__():得到迭代器本身,说白了调了和没调一个样,返回的就是他自己

    dic = {'a': 1, 'b': 2, 'c': 3}
    # dic.__iter__()
    # 字典本身没next方法
    
    dic_iterator = dic.__iter__()
    
    print(dic_iterator.__iter__() is dic_iterator.__iter__())
    
    # 输出 True
    
for循环的工作原理

for循环可以称之为迭代器循环,while循环叫条件循环。

d = {'a': 1, 'b': 2, 'c': 3}

for k in d:
    print(k)

#1. d.__iter__()得到一个迭代器对象
#2. 迭代器对象.__iter__() 拿到一个返回值,然后将该返回值赋值给k
#3. 循环往复步骤2,直到抛出StopIteration 异常,for循环会捕捉异常然后结束循环


# 为什么python为迭代器对象内置一个iter,为了让for循环的工作原理统一起来
with open('a.txt', mode='rt', encoding='utf-8') as f:
    for line in f: # f.__iter__(),f是一个迭代器对象,迭代器对象调iter方法还是本身
        print(line)

迭代器优缺点总结

优点:

  1. 为序列和非序列提供了一种统一的迭代取值方式
  2. 惰性计算:迭代器对象表示的只是一个数据流,可以只在需要时才去调用next计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有元素都存放在内存中,受内存大小的限制,可以存放的值的个数是有限的。

缺点:

  1. 除非取尽,否则无法或者迭代器的长度
  2. 只能去下一个值,不能回到开始,更像 一次性 的,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是再次迭代同一个对象,只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或多个循环使用同一个迭代器,必然只会有一个循环能取到值。

生成器

生成器就是自定义迭代器。

有了yield关键字,就有了一种自定义迭代器的实现方式,yield可以用于返回值,但不体育return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值。

# 如何得到自定义的迭代器:
# 在函数内一旦存在yield关键字,调用函数并不会执行函数体代码,会返回一个生成器对象,生成器即自定义迭代器
def func():
    print('第一次')
    yield 1
    print('第二次')
    yield 2
    print('第三次')
    yield 3
    print('第四次')

g = func()
print(g)

# <generator object func at 0x0000021AA99A0D60>
# 生成器就是迭代器
# g.__iter__() 
# g.__next__()

# 会除非函数体代码的运行,然后遇到yield停下来,将yield后的值当做本次调用的结果返回
res1 = g.__next__()
print(res1)

"""
<generator object func at 0x0000023934C00D60>
第一次
1
"""

总结

  1. 面向对象编程中的成员

    • 变量
      • 实例变量
      • 类变量
  • 方法
    - 绑定方法
    - 类方法
    - 静态方法
    • 属性
  1. 成员修饰符
  2. 对象中的数据嵌套
  3. 特殊成员
  4. 重要概念:
    • 迭代器
    • 生成器
    • 可迭代对象

作业

  1. 列举面向对象的成员并简述他们的特点。

  2. @staticmethod 和 @classmethod的作用是什么?

  3. 面向对象中如何让成员变为私有。

  4. __new__方法的作用?

  5. 简述你理解的:迭代器、生成器、可迭代对象。

  6. 看代码写结果

    class Foo(object):
        a1 = 1
        
        def __init__(self,num):
            self.num = num
            
        def show_data(self):
            print(self.num+self.a1)
        
    obj1 = Foo(666)
    obj2 = Foo(999)
    
    print(obj1.num)
    print(obj1.a1)
    
    obj1.num = 18
    obj1.a1 = 99
    
    print(obj1.num)
    print(obj1.a1)
    
    print(obj2.a1)
    print(obj2.num)
    print(obj2.num)
    print(Foo.a1)
    print(obj1.a1)
    
  7. 看代码写结果,注意返回值。

    class Foo(object):
        
        def f1(self):
            return 999
        
        def f2(self):
            v = self.f1()
            print('f2')
            return v
        
        def f3(self):
            print('f3')
            return self.f2()
        
        def run(self):
            result = self.f3()
            print(result)
    
    obj = Foo()
    v1 = obj.run()
    print(v1)
    
  8. 看代码写结果【如果有错误,则标注错误即可,并且假设程序报错可以继续执行】

    class Foo(object):
        
        def f1(self):
            print('f1')
    
        @staticmethod
        def f2():
            print('f2')
            
    obj = Foo()
    obj.f1()
    obj.f2()
    
    Foo.f1()
    Foo.f2()
    
  9. 看代码写结果【如果有错误,则标注错误即可,并且假设程序报错可以继续执行】

    class Foo(object):
        
        def f1(self):
            print('f1')
            self.f2()
            self.f3()
    
        @classmethod
        def f2(cls):
              print('f2')
    
        @staticmethod
        def f3():
              print('f3')
    
    obj = Foo()
    obj.f1()
    
  10. 看代码写结果【如果有错误,则标注错误即可,并且假设程序报错可以继续执行】

    class Base(object):
        @classmethod
        def f2(cls):
              print('f2')
    
        @staticmethod
        def f3():
              print('f3')
    
    class Foo(Base):
        def f1(self):
            print('f1')
            self.f2()
            self.f3()
    
    obj = Foo()
    obj.f1()
    
  11. 看代码写结果【如果有错误,则标注错误即可,并且假设程序报错可以继续执行】

    class Foo(object):
        a1 = 1
        __a2 = 2
        
        def __init__(self,num):
            self.num = num
            self.__salary = 1000
            
         def show_data(self):
             print(self.num+self.a1)
        
    obj = Foo(666)
    
    print(obj.num)
    print(obj.a1)
    print(obj.__salary)
    print(obj.__a2)
    print(Foo.a1)
    print(Foo.__a2)
    obj.show_data()
    
  12. 看代码写结果

    class Foo(object):
    
        def __init__(self, age):
            self.age = age
    
        def display(self):
            print(self.age)
    
    
    data_list = [Foo(8), Foo(9)]
    # print(data_list[0].age)
    # data_list[1].display()
    
    for item in data_list:
        print(item.age, item.display()) 
    
  13. 看代码写结果

    class Base(object):
        def __init__(self, a1):
            self.a1 = a1
    
        def f2(self, arg):
            print(self.a1, arg)
    
    
    class Foo(Base):
        def f2(self, arg):
            print('666')
    
    
    obj_list = [Base(1), Foo(2), Foo(3)]
    
    for item in obj_list:
        item.f2(1)
    
  14. 看代码写结果

    class Foo(object):
        def __init__(self, num):
            self.num = num
            
    v1 = [Foo for i in range(10)]
    v2 = [Foo(5) for i in range(10)]
    v3 = [Foo(i) for i in range(10)]
    
    print(v1)
    print(v2)
    print(v3)
    
  15. 看代码写结果

    class StarkConfig(object):
    
        def __init__(self, num):
            self.num = num
    
        def changelist(self, request):
            print(self.num, request)
    
    
    config_obj_list = [ StarkConfig(1),  StarkConfig(2),  StarkConfig(3) ]
    for item in config_obj_list:
        print(item.num)
    
  16. 看代码写结果

    class StarkConfig(object):
    
        def __init__(self, num):
            self.num = num
    
        def changelist(self, request):
            print(self.num, request)
    
    
    config_obj_list = [StarkConfig(1), StarkConfig(2), StarkConfig(3)]
    for item in config_obj_list:
        item.changelist(666)
    
  17. 看代码写结果

    class StarkConfig(object):
    
        def __init__(self, num):
            self.num = num
    
        def changelist(self, request):
            print(self.num, request)
    
        def run(self):
            self.changelist(999)
    
    
    class RoleConfig(StarkConfig):
    
        def changelist(self, request):
            print(666, self.num)
    
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
    
        def register(self, k, v):
            self._registry[k] = v
    
    
    site = AdminSite()
    
    site.register('光头强', StarkConfig(19))
    site.register('root', StarkConfig(20))
    site.register("admin", RoleConfig(33))
    
    print(len(site._registry))
    
    for k, row in site._registry.items():
        row.changelist(5)
    
    
  18. 看代码写结果(如有报错,请标注报错位置)

    class StarkConfig(object):
        def __init__(self, num):
            self.num = num
        def run(self):
            self()
        def __call__(self, *args, **kwargs):
            print(self.num)
            
    class RoleConfig(StarkConfig):
        def __call__(self, *args, **kwargs):
            print(345)
        def __getitem__(self, item):
            return self.num[item]
        
    v1 = RoleConfig('Geek')
    v2 = StarkConfig("wupeiqi")
    
    print(v1[1])
    print(v2[2])
    
  19. 补全代码

    class Context:
    	pass
    
    
    with Context() as ctx:
        ctx.do_something()
    
  20. 看代码写结果

    class Department(object):
        def __init__(self,title):
            self.title = title
    
    class Person(object):
        def __init__(self,name,age,depart):
            self.name = name
            self.age = age 
            self.depart = depart
    	
        def message(self):
            msg = "我是%s,年龄%s,属于%s" %(self.name,self.age,self.depart.title)
            print(msg)
        
        
    d1 = Department('人事部')
    d2 = Department('销售部')
    
    p1 = Person('光头强',18,d1)
    p2 = Person('Geek',18,d1)
    
    p1.message()
    p2.message()
    
  21. 分析代码关系,并写出正确的输出结果。

    class Node(object):
        def __init__(self, title):
            self.title = title
            self.children = []
    
        def add(self, node):
            self.children.append(node)
    
        def __getitem__(self, item):
            return self.children[item]
    
    
    root = Node("中国")
    
    root.add(Node("河南省"))
    root.add(Node("河北省"))
    
    print(root.title)
    print(root[0])
    print(root[0].title)
    print(root[1])
    print(root[1].title)
    
  22. 分析代码关系,并写出正确的输出结果。

    class Node(object):
        def __init__(self, title):
            self.title = title
            self.children = []
    
        def add(self, node):
            self.children.append(node)
    
        def __getitem__(self, item):
            return self.children[item]
    
    
    root = Node("中国")
    
    root.add(Node("河南省"))
    root.add(Node("河北省"))
    root.add(Node("陕西省"))
    root.add(Node("山东省"))
    
    root[1].add(Node("石家庄"))
    root[1].add(Node("保定"))
    root[1].add(Node("廊坊"))
    
    root[3].add(Node("潍坊"))
    root[3].add(Node("烟台"))
    root[3].add(Node("威海"))
    
    root[1][1].add(Node("雄安"))
    root[1][1].add(Node("望都"))
    
    print(root.title)
    print(root[0].title)
    print(root[1].title)
    print(root[1][0].title)
    print(root[1][2].title)
    print(root[1][1][0].title)
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

-day18面向对象进阶 的相关文章

随机推荐

  • MacOS编译NGINX1.17

    背景 使用Mac的开发者大多数的时候通过 brew 命令安装各类软件 比如 PHP Python Nodejs Nginx 也不例外 默认情况下Nginx安装在 usr local Cellar nginx 通过brew link ngin
  • ImportError: ERROR: recursion is detected during loading of “cv2“ binary extensions. Check OpenCV in

    1 import cv2错误 ImportError ERROR recursion is detected during loading of cv2 binary extensions Check OpenCV installation
  • C/C++语言图形化窗口创建,与设置。

    1 首先我们要引入头文件 include
  • log4j2远程代码执行漏洞原理与漏洞复现(基于vulhub,保姆级的详细教程)

    漏洞原理 啥是log4j2 log4j2是apache下的java应用常见的开源日志库 是一个就Java的日志记录工具 在log4j框架的基础上进行了改进 并引入了丰富的特性 可以控制日志信息输送的目的地为控制台 文件 GUI组建等 被应用
  • pybind11的安装以及库的使用(ubuntu20.14)

    目录 1 安装第三方库 2 安装pybind11 1 源码下载 2 编译安装 1 安装第三方库 sudo apt get install cmake 3 18 2 已经安装cmake 升级一下 sudo pip install upgrad
  • Matlab数据统计与分析(一)

    本文主要讲述matlab在统计分析中的一些简单应用 后续还将推出多项式计算 数据插值及其应用 曲线拟合及其应用 敬请期待 一 求最大元素与最小元素 max 求向量或矩阵的最大元素 min 求向量或矩阵的最小元素 调用格式如下 1 y max
  • 单细胞专题

    单细胞测序的概念 上节我们讲到转录组测序相关内容 这期将继续学习单细胞转录组测序 单细胞测序技术 single cell sequencing 简单来说 就是在单个细胞水平上 对基因组 转录组及表观基因组进行测序分析的技术 图1 图1 单细
  • 借助云开发搭建专属技术博客微信小程序(附源码)

    导语 一直对小程序开发很感兴趣 之前就准备做一款属于自己的小程序 无奈还需要购买云服务器和部署后台 有点麻烦 自从知道有了云开发这个免去服务器搭建和运维的一站式后端云服务 神器 就一鼓作气花了几个周末的时间做了一款自己的博客小程序 如果你也
  • ES写入性能的提升方案

    从社区上看到一个问题 回答了一下 总结了下提高写入性能的方案 服务端 1 refresh refresh interval 1s indices memory index buffer size 10 2 translog Index tr
  • vSphere使用技巧:自定义管理规范使用

    本文转载至 http blog chinaunix net uid 21089721 id 1565198 html 一 前言 我们在使用vCenter Client的时候 常常会使用模板来安装服务器 但是这样就会带来一些问题 例如WIND
  • Windows通过某端口号找对应的进程窗口句柄

    以下为 Qt通过netstat exe程序获取相关信息 通过端口号获取进程ID 的姊妹篇 通过端口号找对应的窗口句柄 以上所提及的API 均为Win32的系统API 不涉及Qt的相关方法
  • Shell Sort 希尔排序

    希尔排序 Shell Sort 又叫做缩小增量排序 diminishing increment sort 是一种很优秀的排序法 算法本身不难理解 也很容易实现 而且它的速度很快 插入排序 Insertion Sort 的一个重要的特点是 如
  • Oracle中没有 if exists(...)

    对于Oracle中没有 if exists 的语法 目前有许多种解决方法 这里先分析常用的三种 推荐使用最后一种 第一种是最常用的 判断count 的值是否为零 如下 declare v cnt number begin select co
  • 如何搭建自己的服务器机房

    1 地下室这种环境 铲成毛坯先做一遍防水防潮抗震套餐 这个便宜 相对 2 找国家电网拉两个不一样变电站的电线杆子来做380V 之前做过一个机房的这种需求 也就二百来万吧 3 每个运营商 不同机房 做两个方向两个井 两条8 16芯缆 运营商大
  • HTML5 详细介绍 及应用实例

    HTML5 概况 什么是 HTML5 HTML 5有两大特点 首先 强化了 Web 网页的表现性能 其次 追加了本地数据库等 Web 应用的功能 HTML 5是近十年来Web开发标准最巨大的飞跃 和以前的版本不同 HTML 5并非仅仅用来表
  • [MySQL]事务ACID详解

    专栏简介 MySql数据库从入门到进阶 题目来源 leetcode 牛客 剑指offer 创作目标 记录学习MySql学习历程 希望在提升自己的同时 帮助他人 与大家一起共同进步 互相成长 学历代表过去 能力代表现在 学习能力代表未来 目录
  • 版本管理工具——SVN

    SVN的下载和安装 1 1SVN服务器端的安装和配置 1 2SVN客户端的安装和配置 SVN的基本操作 SVN的常见问题 3 1解决文件提交冲突 一 SVN服务器端的安装和配置 1 VisualSVN下载 http www visualsv
  • 国内及Github优秀开发人员列表

    自从入了Android软件开发的行道 解决问题和学习过程中免不了会参考别人的思路 浏览博文和门户网站成了最大的入口 下面这些列表取名为 国内及Github优秀开发人员列表 就是浏览后的成果 虽然下述列表出自Android软件开发 文章定为不
  • python科研项目_通过科研人员论文项目等数据,训练识别导师/学生的分类器

    student and teacher classifier 通过科研人员论文项目等数据 训练识别导师 学生的分类器 代码包括特征选择基础 网格搜索确定特征选择方法参数 不平衡数据的处理 oversampling和undersampling
  • -day18面向对象进阶

    day18 面向对象进阶 课程目标 掌握面向对象进阶相关知识点 能更加自如的使用面向对象来进行编程 今日概要 成员 变量 实例变量 类变量 方法 绑定方法 类方法 静态方法 属性 成员修饰符 公有 私有 对象嵌套 特殊成员 对比 问题 洗衣