1""" basic inference routines """ 2 3from collections import abc 4from numbers import Number 5import re 6from typing import Pattern 7 8import numpy as np 9 10from pandas._libs import lib 11 12is_bool = lib.is_bool 13 14is_integer = lib.is_integer 15 16is_float = lib.is_float 17 18is_complex = lib.is_complex 19 20is_scalar = lib.is_scalar 21 22is_decimal = lib.is_decimal 23 24is_interval = lib.is_interval 25 26is_list_like = lib.is_list_like 27 28is_iterator = lib.is_iterator 29 30 31def is_number(obj) -> bool: 32 """ 33 Check if the object is a number. 34 35 Returns True when the object is a number, and False if is not. 36 37 Parameters 38 ---------- 39 obj : any type 40 The object to check if is a number. 41 42 Returns 43 ------- 44 is_number : bool 45 Whether `obj` is a number or not. 46 47 See Also 48 -------- 49 api.types.is_integer: Checks a subgroup of numbers. 50 51 Examples 52 -------- 53 >>> pd.api.types.is_number(1) 54 True 55 >>> pd.api.types.is_number(7.15) 56 True 57 58 Booleans are valid because they are int subclass. 59 60 >>> pd.api.types.is_number(False) 61 True 62 63 >>> pd.api.types.is_number("foo") 64 False 65 >>> pd.api.types.is_number("5") 66 False 67 """ 68 return isinstance(obj, (Number, np.number)) 69 70 71def iterable_not_string(obj) -> bool: 72 """ 73 Check if the object is an iterable but not a string. 74 75 Parameters 76 ---------- 77 obj : The object to check. 78 79 Returns 80 ------- 81 is_iter_not_string : bool 82 Whether `obj` is a non-string iterable. 83 84 Examples 85 -------- 86 >>> iterable_not_string([1, 2, 3]) 87 True 88 >>> iterable_not_string("foo") 89 False 90 >>> iterable_not_string(1) 91 False 92 """ 93 return isinstance(obj, abc.Iterable) and not isinstance(obj, str) 94 95 96def is_file_like(obj) -> bool: 97 """ 98 Check if the object is a file-like object. 99 100 For objects to be considered file-like, they must 101 be an iterator AND have either a `read` and/or `write` 102 method as an attribute. 103 104 Note: file-like objects must be iterable, but 105 iterable objects need not be file-like. 106 107 Parameters 108 ---------- 109 obj : The object to check 110 111 Returns 112 ------- 113 is_file_like : bool 114 Whether `obj` has file-like properties. 115 116 Examples 117 -------- 118 >>> import io 119 >>> buffer = io.StringIO("data") 120 >>> is_file_like(buffer) 121 True 122 >>> is_file_like([1, 2, 3]) 123 False 124 """ 125 if not (hasattr(obj, "read") or hasattr(obj, "write")): 126 return False 127 128 if not hasattr(obj, "__iter__"): 129 return False 130 131 return True 132 133 134def is_re(obj) -> bool: 135 """ 136 Check if the object is a regex pattern instance. 137 138 Parameters 139 ---------- 140 obj : The object to check 141 142 Returns 143 ------- 144 is_regex : bool 145 Whether `obj` is a regex pattern. 146 147 Examples 148 -------- 149 >>> is_re(re.compile(".*")) 150 True 151 >>> is_re("foo") 152 False 153 """ 154 return isinstance(obj, Pattern) 155 156 157def is_re_compilable(obj) -> bool: 158 """ 159 Check if the object can be compiled into a regex pattern instance. 160 161 Parameters 162 ---------- 163 obj : The object to check 164 165 Returns 166 ------- 167 is_regex_compilable : bool 168 Whether `obj` can be compiled as a regex pattern. 169 170 Examples 171 -------- 172 >>> is_re_compilable(".*") 173 True 174 >>> is_re_compilable(1) 175 False 176 """ 177 try: 178 re.compile(obj) 179 except TypeError: 180 return False 181 else: 182 return True 183 184 185def is_array_like(obj) -> bool: 186 """ 187 Check if the object is array-like. 188 189 For an object to be considered array-like, it must be list-like and 190 have a `dtype` attribute. 191 192 Parameters 193 ---------- 194 obj : The object to check 195 196 Returns 197 ------- 198 is_array_like : bool 199 Whether `obj` has array-like properties. 200 201 Examples 202 -------- 203 >>> is_array_like(np.array([1, 2, 3])) 204 True 205 >>> is_array_like(pd.Series(["a", "b"])) 206 True 207 >>> is_array_like(pd.Index(["2016-01-01"])) 208 True 209 >>> is_array_like([1, 2, 3]) 210 False 211 >>> is_array_like(("a", "b")) 212 False 213 """ 214 return is_list_like(obj) and hasattr(obj, "dtype") 215 216 217def is_nested_list_like(obj) -> bool: 218 """ 219 Check if the object is list-like, and that all of its elements 220 are also list-like. 221 222 Parameters 223 ---------- 224 obj : The object to check 225 226 Returns 227 ------- 228 is_list_like : bool 229 Whether `obj` has list-like properties. 230 231 Examples 232 -------- 233 >>> is_nested_list_like([[1, 2, 3]]) 234 True 235 >>> is_nested_list_like([{1, 2, 3}, {1, 2, 3}]) 236 True 237 >>> is_nested_list_like(["foo"]) 238 False 239 >>> is_nested_list_like([]) 240 False 241 >>> is_nested_list_like([[1, 2, 3], 1]) 242 False 243 244 Notes 245 ----- 246 This won't reliably detect whether a consumable iterator (e. g. 247 a generator) is a nested-list-like without consuming the iterator. 248 To avoid consuming it, we always return False if the outer container 249 doesn't define `__len__`. 250 251 See Also 252 -------- 253 is_list_like 254 """ 255 return ( 256 is_list_like(obj) 257 and hasattr(obj, "__len__") 258 and len(obj) > 0 259 and all(is_list_like(item) for item in obj) 260 ) 261 262 263def is_dict_like(obj) -> bool: 264 """ 265 Check if the object is dict-like. 266 267 Parameters 268 ---------- 269 obj : The object to check 270 271 Returns 272 ------- 273 is_dict_like : bool 274 Whether `obj` has dict-like properties. 275 276 Examples 277 -------- 278 >>> is_dict_like({1: 2}) 279 True 280 >>> is_dict_like([1, 2, 3]) 281 False 282 >>> is_dict_like(dict) 283 False 284 >>> is_dict_like(dict()) 285 True 286 """ 287 dict_like_attrs = ("__getitem__", "keys", "__contains__") 288 return ( 289 all(hasattr(obj, attr) for attr in dict_like_attrs) 290 # [GH 25196] exclude classes 291 and not isinstance(obj, type) 292 ) 293 294 295def is_named_tuple(obj) -> bool: 296 """ 297 Check if the object is a named tuple. 298 299 Parameters 300 ---------- 301 obj : The object to check 302 303 Returns 304 ------- 305 is_named_tuple : bool 306 Whether `obj` is a named tuple. 307 308 Examples 309 -------- 310 >>> from collections import namedtuple 311 >>> Point = namedtuple("Point", ["x", "y"]) 312 >>> p = Point(1, 2) 313 >>> 314 >>> is_named_tuple(p) 315 True 316 >>> is_named_tuple((1, 2)) 317 False 318 """ 319 return isinstance(obj, tuple) and hasattr(obj, "_fields") 320 321 322def is_hashable(obj) -> bool: 323 """ 324 Return True if hash(obj) will succeed, False otherwise. 325 326 Some types will pass a test against collections.abc.Hashable but fail when 327 they are actually hashed with hash(). 328 329 Distinguish between these and other types by trying the call to hash() and 330 seeing if they raise TypeError. 331 332 Returns 333 ------- 334 bool 335 336 Examples 337 -------- 338 >>> import collections 339 >>> a = ([],) 340 >>> isinstance(a, collections.abc.Hashable) 341 True 342 >>> is_hashable(a) 343 False 344 """ 345 # Unfortunately, we can't use isinstance(obj, collections.abc.Hashable), 346 # which can be faster than calling hash. That is because numpy scalars 347 # fail this test. 348 349 # Reconsider this decision once this numpy bug is fixed: 350 # https://github.com/numpy/numpy/issues/5562 351 352 try: 353 hash(obj) 354 except TypeError: 355 return False 356 else: 357 return True 358 359 360def is_sequence(obj) -> bool: 361 """ 362 Check if the object is a sequence of objects. 363 String types are not included as sequences here. 364 365 Parameters 366 ---------- 367 obj : The object to check 368 369 Returns 370 ------- 371 is_sequence : bool 372 Whether `obj` is a sequence of objects. 373 374 Examples 375 -------- 376 >>> l = [1, 2, 3] 377 >>> 378 >>> is_sequence(l) 379 True 380 >>> is_sequence(iter(l)) 381 False 382 """ 383 try: 384 iter(obj) # Can iterate over it. 385 len(obj) # Has a length associated with it. 386 return not isinstance(obj, (str, bytes)) 387 except (TypeError, AttributeError): 388 return False 389 390 391def is_dataclass(item): 392 """ 393 Checks if the object is a data-class instance 394 395 Parameters 396 ---------- 397 item : object 398 399 Returns 400 -------- 401 is_dataclass : bool 402 True if the item is an instance of a data-class, 403 will return false if you pass the data class itself 404 405 Examples 406 -------- 407 >>> from dataclasses import dataclass 408 >>> @dataclass 409 ... class Point: 410 ... x: int 411 ... y: int 412 413 >>> is_dataclass(Point) 414 False 415 >>> is_dataclass(Point(0,2)) 416 True 417 418 """ 419 try: 420 from dataclasses import is_dataclass 421 422 return is_dataclass(item) and not isinstance(item, type) 423 except ImportError: 424 return False 425