@@ -1081,7 +1081,9 @@ def __setitem__(self, key, value) -> None:
10811081
10821082 try :
10831083 self ._set_with_engine (key , value )
1084- except (KeyError , ValueError ):
1084+ except KeyError :
1085+ # We have a scalar (or for MultiIndex or object-dtype, scalar-like)
1086+ # key that is not present in self.index.
10851087 if is_integer (key ) and self .index .inferred_type != "integer" :
10861088 # positional setter
10871089 if not self .index ._should_fallback_to_positional :
@@ -1102,9 +1104,15 @@ def __setitem__(self, key, value) -> None:
11021104 # GH#12862 adding a new key to the Series
11031105 self .loc [key ] = value
11041106
1105- except (InvalidIndexError , TypeError ) as err :
1107+ except (TypeError , ValueError ):
1108+ # The key was OK, but we cannot set the value losslessly
1109+ indexer = self .index .get_loc (key )
1110+ self ._set_values (indexer , value )
1111+
1112+ except InvalidIndexError as err :
11061113 if isinstance (key , tuple ) and not isinstance (self .index , MultiIndex ):
11071114 # cases with MultiIndex don't get here bc they raise KeyError
1115+ # e.g. test_basic_getitem_setitem_corner
11081116 raise KeyError (
11091117 "key of type tuple not found and not a MultiIndex"
11101118 ) from err
@@ -1163,17 +1171,19 @@ def _set_with(self, key, value):
11631171 # Without this, the call to infer_dtype will consume the generator
11641172 key = list (key )
11651173
1166- key_type = lib .infer_dtype (key , skipna = False )
1174+ if not self .index ._should_fallback_to_positional :
1175+ # Regardless of the key type, we're treating it as labels
1176+ self ._set_labels (key , value )
11671177
1168- # Note: key_type == "boolean" should not occur because that
1169- # should be caught by the is_bool_indexer check in __setitem__
1170- if key_type == "integer" :
1171- if not self .index ._should_fallback_to_positional :
1172- self ._set_labels (key , value )
1173- else :
1174- self ._set_values (key , value )
11751178 else :
1176- self .loc [key ] = value
1179+ # Note: key_type == "boolean" should not occur because that
1180+ # should be caught by the is_bool_indexer check in __setitem__
1181+ key_type = lib .infer_dtype (key , skipna = False )
1182+
1183+ if key_type == "integer" :
1184+ self ._set_values (key , value )
1185+ else :
1186+ self ._set_labels (key , value )
11771187
11781188 def _set_labels (self , key , value ) -> None :
11791189 key = com .asarray_tuplesafe (key )
0 commit comments