python类Iterator()的实例源码

mparray.py 文件源码 项目:mpnum 作者: dseuss 项目源码 文件源码 阅读 30 收藏 0 点赞 0 评论 0
def axis_iter(self, axes=0):
        """Returns an iterator yielding Sub-MPArrays of ``self`` by iterating
        over the specified physical axes.

        **Example:** If ``self`` represents a bipartite (i.e. length 2)
        array with 2 physical dimensions on each site ``A[(k,l), (m,n)]``,
        ``self.axis_iter(0)`` is equivalent to::

            (A[(k, :), (m, :)] for m in range(...) for k in range(...))

        :param axes: Iterable or int specifiying the physical axes to iterate
            over (default 0 for each site)
        :returns: Iterator over :class:`.MPArray`

        """
        if not isinstance(axes, collections.Iterable):
            axes = it.repeat(axes, len(self))

        ltens_iter = it.product(*(iter(np.rollaxis(lten, i + 1))
                                  for i, lten in zip(axes, self.lt)))
        return (MPArray(ltens) for ltens in ltens_iter)

    ##########################
    #  Algebraic operations  #
    ##########################
mparray.py 文件源码 项目:mpnum 作者: dseuss 项目源码 文件源码 阅读 30 收藏 0 点赞 0 评论 0
def _extract_factors(tens, ndims):
    """Extract iteratively the leftmost MPO tensor with given number of
    legs by a qr-decomposition

    :param np.ndarray tens: Full tensor to be factorized
    :param ndims: Number of physical legs per site or iterator over number of
        physical legs
    :returns: List of local tensors with given number of legs yielding a
        factorization of tens
    """
    current = next(ndims) if isinstance(ndims, collections.Iterator) else ndims
    if tens.ndim == current + 2:
        return [tens]
    elif tens.ndim < current + 2:
        raise AssertionError("Number of remaining legs insufficient.")
    else:
        unitary, rest = qr(tens.reshape((np.prod(tens.shape[:current + 1]), -1)))

        unitary = unitary.reshape(tens.shape[:current + 1] + rest.shape[:1])
        rest = rest.reshape(rest.shape[:1] + tens.shape[current + 1:])

        return [unitary] + _extract_factors(rest, ndims)
mparray.py 文件源码 项目:mpnum 作者: dseuss 项目源码 文件源码 阅读 31 收藏 0 点赞 0 评论 0
def _ltens_to_array(ltens):
    """Computes the full array representation from an iterator yielding the
    local tensors. Note that it does not get rid of virtual legs.

    :param ltens: Iterator over local tensors
    :returns: numpy.ndarray representing the contracted MPA

    """
    ltens = ltens if isinstance(ltens, collections.Iterator) else iter(ltens)
    res = first = next(ltens)
    for tens in ltens:
        res = matdot(res, tens)
    if res is first:
        # Always return a writable array, even if len(ltens) == 1.
        res = res.copy()
    return res


################################################
#  Helper methods for variational compression  #
################################################
types.py 文件源码 项目:magic-constraints 作者: huntzhan 项目源码 文件源码 阅读 25 收藏 0 点赞 0 评论 0
def _class___init__(self, iterator):
        if self.partial_cls is None:
            raise MagicTypeError(
                'Iterator should be specified.'
            )

        if not isinstance(iterator, self.main_cls):
            raise MagicTypeError(
                'require Iterator.',
                iterator=iterator,
            )

        if isinstance(self.partial_cls, tuple):
            # Iterator[T, ...]. Checking on:
            # 1. the number of elements in the iterator.
            # 2. the type of each element.
            self.case = self.ITERATOR_CASE_LENGTH
            self._type_idx = 0
        else:
            # Iterator[T]. Check only the type of element. There's no
            # limitation on the length of iterator.
            self.case = self.ITERATOR_CASE_NO_LENGTH

        self.iterator = iterator
util.py 文件源码 项目:aptrepo 作者: jwodder 项目源码 文件源码 阅读 25 收藏 0 点赞 0 评论 0
def for_json(obj):
    if hasattr(obj, 'for_json'):
        return obj.for_json()
    elif isinstance(obj, datetime):
        return obj.isoformat()
    elif isinstance(obj, collections.Mapping):
        # This includes all types in debian.deb822.
        return {str(k): obj[k] for k in obj}
    elif isinstance(obj, (collections.Iterator, tuple, set, frozenset)):
        ### TODO: Sort sets and frozensets?
        return list(obj)
    else:
        try:
            data = vars(obj).copy()
        except TypeError:
            return repr(obj)
        else:
            data["__class__"] = type(obj).__name__
            return data
test_collections.py 文件源码 项目:zippy 作者: securesystemslab 项目源码 文件源码 阅读 21 收藏 0 点赞 0 评论 0
def test_Iterator(self):
        non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
        for x in non_samples:
            self.assertNotIsInstance(x, Iterator)
            self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
        samples = [iter(bytes()), iter(str()),
                   iter(tuple()), iter(list()), iter(dict()),
                   iter(set()), iter(frozenset()),
                   iter(dict().keys()), iter(dict().items()),
                   iter(dict().values()),
                   (lambda: (yield))(),
                   (x for x in []),
                   ]
        for x in samples:
            self.assertIsInstance(x, Iterator)
            self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
        self.validate_abstract_methods(Iterator, '__next__', '__iter__')

        # Issue 10565
        class NextOnly:
            def __next__(self):
                yield 1
                raise StopIteration
        self.assertNotIsInstance(NextOnly(), Iterator)
frame.py 文件源码 项目:PyDataLondon29-EmbarrassinglyParallelDAWithAWSLambda 作者: SignalMedia 项目源码 文件源码 阅读 33 收藏 0 点赞 0 评论 0
def iteritems(self):
        """
        Iterator over (column name, Series) pairs.

        See also
        --------
        iterrows : Iterate over DataFrame rows as (index, Series) pairs.
        itertuples : Iterate over DataFrame rows as namedtuples of the values.

        """
        if self.columns.is_unique and hasattr(self, '_item_cache'):
            for k in self.columns:
                yield k, self._get_item_cache(k)
        else:
            for i, k in enumerate(self.columns):
                yield k, self._ixs(i, axis=1)
utils.py 文件源码 项目:odin 作者: imito 项目源码 文件源码 阅读 25 收藏 0 点赞 0 评论 0
def __delitem__(self, key):
    if self.read_only:
      return
    query = """DELETE FROM {tb} WHERE {cond};"""
    if isinstance(key, (tuple, list, Iterator, np.ndarray)):
      key = [str(k) for k in key]
    else:
      key = [str(key)]
    # ====== check if key in cache ====== #
    db_key = []
    for k in key:
      if k in self.current_cache:
        del self.current_cache[k]
      else:
        db_key.append(k)
    # ====== remove key from db ====== #
    self.cursor.execute(
        query.format(tb=self._current_table,
                     cond='key IN ("%s")' % ', '.join(db_key)))
    self.connection.commit()
test_pathlib.py 文件源码 项目:ouroboros 作者: pybee 项目源码 文件源码 阅读 26 收藏 0 点赞 0 评论 0
def test_glob_common(self):
        def _check(glob, expected):
            self.assertEqual(set(glob), { P(BASE, q) for q in expected })
        P = self.cls
        p = P(BASE)
        it = p.glob("fileA")
        self.assertIsInstance(it, collections.Iterator)
        _check(it, ["fileA"])
        _check(p.glob("fileB"), [])
        _check(p.glob("dir*/file*"), ["dirB/fileB", "dirC/fileC"])
        if symlink_skip_reason:
            _check(p.glob("*A"), ['dirA', 'fileA'])
        else:
            _check(p.glob("*A"), ['dirA', 'fileA', 'linkA'])
        if symlink_skip_reason:
            _check(p.glob("*B/*"), ['dirB/fileB'])
        else:
            _check(p.glob("*B/*"), ['dirB/fileB', 'dirB/linkD',
                                    'linkB/fileB', 'linkB/linkD'])
        if symlink_skip_reason:
            _check(p.glob("*/fileB"), ['dirB/fileB'])
        else:
            _check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB'])
test_pathlib.py 文件源码 项目:ouroboros 作者: pybee 项目源码 文件源码 阅读 30 收藏 0 点赞 0 评论 0
def test_rglob_common(self):
        def _check(glob, expected):
            self.assertEqual(set(glob), { P(BASE, q) for q in expected })
        P = self.cls
        p = P(BASE)
        it = p.rglob("fileA")
        self.assertIsInstance(it, collections.Iterator)
        _check(it, ["fileA"])
        _check(p.rglob("fileB"), ["dirB/fileB"])
        _check(p.rglob("*/fileA"), [])
        if symlink_skip_reason:
            _check(p.rglob("*/fileB"), ["dirB/fileB"])
        else:
            _check(p.rglob("*/fileB"), ["dirB/fileB", "dirB/linkD/fileB",
                                        "linkB/fileB", "dirA/linkC/fileB"])
        _check(p.rglob("file*"), ["fileA", "dirB/fileB",
                                  "dirC/fileC", "dirC/dirD/fileD"])
        p = P(BASE, "dirC")
        _check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"])
        _check(p.rglob("*/*"), ["dirC/dirD/fileD"])
test_pathlib.py 文件源码 项目:kbe_server 作者: xiaohaoppy 项目源码 文件源码 阅读 23 收藏 0 点赞 0 评论 0
def test_glob_common(self):
        def _check(glob, expected):
            self.assertEqual(set(glob), { P(BASE, q) for q in expected })
        P = self.cls
        p = P(BASE)
        it = p.glob("fileA")
        self.assertIsInstance(it, collections.Iterator)
        _check(it, ["fileA"])
        _check(p.glob("fileB"), [])
        _check(p.glob("dir*/file*"), ["dirB/fileB", "dirC/fileC"])
        if symlink_skip_reason:
            _check(p.glob("*A"), ['dirA', 'fileA'])
        else:
            _check(p.glob("*A"), ['dirA', 'fileA', 'linkA'])
        if symlink_skip_reason:
            _check(p.glob("*B/*"), ['dirB/fileB'])
        else:
            _check(p.glob("*B/*"), ['dirB/fileB', 'dirB/linkD',
                                    'linkB/fileB', 'linkB/linkD'])
        if symlink_skip_reason:
            _check(p.glob("*/fileB"), ['dirB/fileB'])
        else:
            _check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB'])
test_pathlib.py 文件源码 项目:kbe_server 作者: xiaohaoppy 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def test_rglob_common(self):
        def _check(glob, expected):
            self.assertEqual(set(glob), { P(BASE, q) for q in expected })
        P = self.cls
        p = P(BASE)
        it = p.rglob("fileA")
        self.assertIsInstance(it, collections.Iterator)
        # XXX cannot test because of symlink loops in the test setup
        #_check(it, ["fileA"])
        #_check(p.rglob("fileB"), ["dirB/fileB"])
        #_check(p.rglob("*/fileA"), [""])
        #_check(p.rglob("*/fileB"), ["dirB/fileB"])
        #_check(p.rglob("file*"), ["fileA", "dirB/fileB"])
        # No symlink loops here
        p = P(BASE, "dirC")
        _check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"])
        _check(p.rglob("*/*"), ["dirC/dirD/fileD"])
utils.py 文件源码 项目:mizani 作者: has2k1 项目源码 文件源码 阅读 21 收藏 0 点赞 0 评论 0
def first_element(obj):
    """
    Return the first element of `obj`

    Parameters
    ----------
    obj : iterable
        Should not be an iterator

    Returns
    -------
    out : object
        First element of `obj`. Raise a class:`StopIteration`
        exception if `obj` is empty.
    """
    if isinstance(obj, Iterator):
        raise RuntimeError(
            "Cannot get the first element of an iterator")
    return next(iter(obj))
DataFeeder.py 文件源码 项目:TFCommon 作者: MU94W 项目源码 文件源码 阅读 27 收藏 0 点赞 0 评论 0
def split_strategy(self, many_records) -> collections.Iterator:
        pass
mparray.py 文件源码 项目:mpnum 作者: dseuss 项目源码 文件源码 阅读 29 收藏 0 点赞 0 评论 0
def sumup(mpas, weights=None):
    """Returns the sum of the MPArrays in ``mpas``. Same as

    .. code-block:: python

        functools.reduce(mp.MPArray.__add__, mpas)

    but should be faster as we can get rid of intermediate allocations.

    :param mpas: Iterator over :class:`~MPArray`
    :returns: Sum of ``mpas``

    """
    mpas = list(mpas)
    length = len(mpas[0])
    assert all(len(mpa) == length for mpa in mpas)

    if length == 1:
        if weights is None:
            return MPArray([sum(mpa.lt[0] for mpa in mpas)])
        else:
            return MPArray([sum(w * mpa.lt[0] for w, mpa in zip(weights, mpas))])

    ltensiter = [iter(mpa.lt) for mpa in mpas]
    if weights is None:
        ltens = [np.concatenate([next(lt) for lt in ltensiter], axis=-1)]
    else:
        ltens = [np.concatenate([w * next(lt)
                                 for w, lt in zip(weights, ltensiter)], axis=-1)]
    ltens += [_local_add([next(lt) for lt in ltensiter])
              for _ in range(length - 2)]
    ltens += [np.concatenate([next(lt) for lt in ltensiter], axis=0)]

    return MPArray(ltens)
types.py 文件源码 项目:magic-constraints 作者: huntzhan 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def _metaclass_check_getitem_type_decl(cls, type_decl):
        # 1. Iterator[T, ...]
        if isinstance(type_decl, tuple):
            for T in type_decl:
                if nontype_object(T):
                    return False
            return True

        # 2. Iterator[T]
        elif type_object(type_decl):
            return True

        else:
            return False
types.py 文件源码 项目:magic-constraints 作者: huntzhan 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def _metaclass_check_instance(cls, instance):
        if cls.partial_cls or not check_type_of_instance(cls, instance):
            return False
        else:
            # is Iterator and not Iterator[...].
            return True
types.py 文件源码 项目:magic-constraints 作者: huntzhan 项目源码 文件源码 阅读 46 收藏 0 点赞 0 评论 0
def _class___iter__(self):
        return Iterator[self.partial_cls](iter(self.iterable))
constraint.py 文件源码 项目:magic-constraints 作者: huntzhan 项目源码 文件源码 阅读 24 收藏 0 点赞 0 评论 0
def wrapper_for_deferred_checking(self):
        if not issubclass(self.type_, BasicMagicType):
            return None

        if issubclass(self.type_.main_cls, (abc.Iterator, abc.Callable)) and\
                self.type_.partial_cls:
            return self.type_

        else:
            return None
test_scaffold.py 文件源码 项目:ababe 作者: unkcpz 项目源码 文件源码 阅读 23 收藏 0 点赞 0 评论 0
def test_gen_speckle(self):
        c = Specie("Cu")
        t = Specie("Ti")
        sites   = [[[c, c],
                    [t, t]],

                   [[c, t],
                    [t, c]]]
        self.sg = SitesGrid(sites)
        gen = SitesGrid.gen_speckle(Specie("Cu"), (2,2,2), Specie("Ti"), 4)
        from collections import Iterator
        self.assertIsInstance(gen, Iterator)
        self.assertIn(self.sg, gen)
        self.assertEqual(next(gen).to_array().sum(), 204)
        self.assertEqual(next(gen).to_array().sum(), 204)
test_scaffold.py 文件源码 项目:ababe 作者: unkcpz 项目源码 文件源码 阅读 24 收藏 0 点赞 0 评论 0
def test_gen_speckle(self):
        c = Specie("Cu")
        t = Specie("Ti")
        sites   = [[[c, c],
                    [t, t]],

                   [[c, t],
                    [t, c]]]
        sg = SitesGrid(sites)
        gen = CStru.gen_speckle(self.m, Specie("Cu"), (2,2,2), Specie("Ti"), 4)
        from collections import Iterator
        self.assertIsInstance(gen, Iterator)
        self.assertIn(CStru(self.m, sg), gen)
        self.assertEqual(next(gen).get_array().sum(), 204)
        self.assertEqual(next(gen).get_array().sum(), 204)
pyfil.py 文件源码 项目:pyfil 作者: ninjaaron 项目源码 文件源码 阅读 20 收藏 0 点赞 0 评论 0
def run(expressions, args, namespace={}):
    func = exec if args.exec else eval
    for expr in expressions:
        if args.exception_handler:
            exception, handler = tuple(
                    i.strip() for i in
                    args.exception_handler.split(':', maxsplit=1))
            try:
                value = func(expr, namespace)
            except __builtins__[exception]:
                try:
                    value = func(handler, namespace)
                except Exception as e:
                    value = handle_errors(e, args)
                    continue
            except Exception as e:
                value = handle_errors(e, args)
                continue
        else:
            try:
                value = func(expr, namespace)
            except Exception as e:
                value = handle_errors(e, args)
                continue

        if not args.exec:
            namespace.update(x=value)

    if not (args.quiet or args.exec):
        if args.join is not None and isinstance(value, collections.Iterable):
            print(ast.literal_eval("'''" + args.join.replace("'", r"\'") +
                "'''").join(map(str, value)))
        elif value is None:
            pass
        elif isinstance(value, collections.Iterator):
            for i in value:
                print_obj(i)
        else:
            indent = None if (args.loop or args.force_oneline_json) else 2
            print_obj(value, indent)
template.py 文件源码 项目:datatest 作者: shawnbrown 项目源码 文件源码 阅读 26 收藏 0 点赞 0 评论 0
def test_06_iterator(self):
            """calling __iter__() should return an iterator"""
            self.assertIsInstance(self.source.__iter__(), Iterator)
test_collections.py 文件源码 项目:zippy 作者: securesystemslab 项目源码 文件源码 阅读 26 收藏 0 点赞 0 评论 0
def test_direct_subclassing(self):
        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
            class C(B):
                pass
            self.assertTrue(issubclass(C, B))
            self.assertFalse(issubclass(int, C))
test_collections.py 文件源码 项目:zippy 作者: securesystemslab 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def test_registration(self):
        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
            class C:
                __hash__ = None  # Make sure it isn't hashable by default
            self.assertFalse(issubclass(C, B), B.__name__)
            B.register(C)
            self.assertTrue(issubclass(C, B))
lazyarray.py 文件源码 项目:lazyarray 作者: NeuralEnsemble 项目源码 文件源码 阅读 26 收藏 0 点赞 0 评论 0
def _partially_evaluate(self, addr, simplify=False):
        """
        Return part of the lazy array.
        """
        if self.is_homogeneous:
            if simplify:
                base_val = self.base_value
            else:
                base_val = self._homogeneous_array(addr) * self.base_value
        elif isinstance(self.base_value, (int, long, numpy.integer, float, bool)):
            base_val = self._homogeneous_array(addr) * self.base_value
        elif isinstance(self.base_value, numpy.ndarray):
            base_val = self.base_value[addr]
        elif have_scipy and sparse.issparse(self.base_value):  # For sparse matrices larr[2, :]
            base_val = self.base_value[addr]
        elif callable(self.base_value):
            indices = self._array_indices(addr)
            base_val = self.base_value(*indices)
            if isinstance(base_val, numpy.ndarray) and base_val.shape == (1,):
                base_val = base_val[0]
        elif hasattr(self.base_value, "lazily_evaluate"):
            base_val = self.base_value.lazily_evaluate(addr, shape=self._shape)
        elif isinstance(self.base_value, VectorizedIterable):
            partial_shape = self._partial_shape(addr)
            if partial_shape:
                n = reduce(operator.mul, partial_shape)
            else:
                n = 1
            base_val = self.base_value.next(n)  # note that the array contents will depend on the order of access to elements
            if n == 1:
                base_val = base_val[0]
            elif partial_shape and base_val.shape != partial_shape:
                base_val = base_val.reshape(partial_shape)
        elif isinstance(self.base_value, collections.Iterator):
            raise NotImplementedError("coming soon...")
        else:
            raise ValueError("invalid base value for array (%s)" % self.base_value)
        return self._apply_operations(base_val, addr, simplify=simplify)
lazyarray.py 文件源码 项目:lazyarray 作者: NeuralEnsemble 项目源码 文件源码 阅读 24 收藏 0 点赞 0 评论 0
def evaluate(self, simplify=False, empty_val=0):
        """
        Return the lazy array as a real NumPy array.

        If the array is homogeneous and ``simplify`` is ``True``, return a
        single numerical value.
        """
        # need to catch the situation where a generator-based larray is evaluated a second time
        if self.is_homogeneous:
            if simplify:
                x = self.base_value
            else:
                x = self.base_value * numpy.ones(self._shape, dtype=self.dtype)
        elif isinstance(self.base_value, (int, long, numpy.integer, float, bool, numpy.bool_)):
            x = self.base_value * numpy.ones(self._shape, dtype=self.dtype)
        elif isinstance(self.base_value, numpy.ndarray):
            x = self.base_value
        elif callable(self.base_value):
            x = numpy.array(numpy.fromfunction(self.base_value, shape=self._shape, dtype=int), dtype=self.dtype)
        elif hasattr(self.base_value, "lazily_evaluate"):
            x = self.base_value.lazily_evaluate(shape=self._shape)
        elif isinstance(self.base_value, VectorizedIterable):
            x = self.base_value.next(self.size)
            if x.shape != self._shape:
                x = x.reshape(self._shape)
        elif have_scipy and sparse.issparse(self.base_value):  # For sparse matrices
            if empty_val!=0:
                x = self.base_value.toarray((sparse.csc_matrix))
                x = numpy.where(x, x, numpy.nan)
            else:
                x = self.base_value.toarray((sparse.csc_matrix))
        elif isinstance(self.base_value, collections.Iterator):
            x = numpy.fromiter(self.base_value, dtype=self.dtype or float, count=self.size)
            if x.shape != self._shape:
                x = x.reshape(self._shape)
        else:
            raise ValueError("invalid base value for array")
        return self._apply_operations(x, simplify=simplify)
test_collections.py 文件源码 项目:oil 作者: oilshell 项目源码 文件源码 阅读 19 收藏 0 点赞 0 评论 0
def test_Iterator(self):
        non_samples = [None, 42, 3.14, 1j, "".encode('ascii'), "", (), [],
            {}, set()]
        for x in non_samples:
            self.assertNotIsInstance(x, Iterator)
            self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
        samples = [iter(str()),
                   iter(tuple()), iter(list()), iter(dict()),
                   iter(set()), iter(frozenset()),
                   iter(dict().keys()), iter(dict().items()),
                   iter(dict().values()),
                   (lambda: (yield))(),
                   (x for x in []),
                   ]
        for x in samples:
            self.assertIsInstance(x, Iterator)
            self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
        self.validate_abstract_methods(Iterator, 'next', '__iter__')

        # Issue 10565
        class NextOnly:
            def __next__(self):
                yield 1
                raise StopIteration
        self.assertNotIsInstance(NextOnly(), Iterator)
        class NextOnlyNew(object):
            def __next__(self):
                yield 1
                raise StopIteration
        self.assertNotIsInstance(NextOnlyNew(), Iterator)
test_collections.py 文件源码 项目:oil 作者: oilshell 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def test_direct_subclassing(self):
        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
            class C(B):
                pass
            self.assertTrue(issubclass(C, B))
            self.assertFalse(issubclass(int, C))
test_collections.py 文件源码 项目:oil 作者: oilshell 项目源码 文件源码 阅读 25 收藏 0 点赞 0 评论 0
def test_registration(self):
        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
            class C:
                __metaclass__ = type
                __hash__ = None  # Make sure it isn't hashable by default
            self.assertFalse(issubclass(C, B), B.__name__)
            B.register(C)
            self.assertTrue(issubclass(C, B))


问题


面经


文章

微信
公众号

扫码关注公众号